Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3546 lines
87 KiB

;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
;===========================================================================
;
; FILE: DSKFRMT.ASM
;
;===========================================================================
;===========================================================================
;Declaration of include files
;===========================================================================
debug equ 0
.xlist
INCLUDE DOSEQUS.INC
INCLUDE DOSMAC.INC
INCLUDE SYSCALL.INC
INCLUDE ERROR.INC
INCLUDE BPB.INC
INCLUDE FOREQU.INC
INCLUDE FORMACRO.INC
INCLUDE IOCTL.INC
INCLUDE FORSWTCH.INC
.list
;===========================================================================
; Declarations for all publics in other modules used by this module
;===========================================================================
;===========================================================================
; Data segment
;===========================================================================
DATA SEGMENT PUBLIC PARA 'DATA'
;Bytes
EXTRN fBigFat :BYTE
EXTRN fBig32Fat :BYTE
EXTRN ExitStatus :BYTE
EXTRN DblFlg :BYTE
EXTRN DriveToFormat :BYTE
EXTRN msgFormatFailure :BYTE
EXTRN msgDiskUnusable :BYTE
EXTRN msgNotSystemDisk :BYTE
EXTRN msgParametersNotSupported:BYTE
EXTRN msgParametersNotSupportedByDrive:BYTE
EXTRN msgHardDiskWarning :BYTE
EXTRN msgDiskWarning :BYTE
EXTRN msgInsertDisk :BYTE
EXTRN msgCrLf :BYTE
EXTRN msgCurrentTrack :BYTE
EXTRN msgFormatComplete :BYTE
EXTRN msgVerify :BYTE
EXTRN msgSetBadClus :BYTE
EXTRN msgSetBadClusDone :BYTE
EXTRN ContinueMsg :BYTE
EXTRN Extended_Error_Msg :BYTE
EXTRN Clustbound_Flag :BYTE
EXTRN Fatal_Error :BYTE
EXTRN FATNotAllInMem :BYTE
EXTRN msgInsufficientMemory :BYTE
EXTRN msgWriteFat :BYTE
;Words
EXTRN FirstHead :WORD
EXTRN FirstCylinder :WORD
EXTRN Formatted_Tracks_Low :WORD
EXTRN Formatted_Tracks_High :WORD
EXTRN Paras_Per_Fat :WORD
EXTRN SwitchMap :WORD
EXTRN SwitchMap2 :WORD
EXTRN Relative_Sector_Low :WORD
EXTRN Relative_Sector_High :WORD
EXTRN Clustbound_Buffer_Seg :WORD
EXTRN Clustbound_Adj_Factor :WORD
EXTRN Clustbound_Spt_Count :WORD
; Dwords
EXTRN TracksLeft :DWORD
EXTRN TracksPerDisk :DWORD
EXTRN sector_in_buffer :DWORD
EXTRN sector_to_read :DWORD
EXTRN TotalClusters :DWORD
EXTRN StartSector :DWORD
EXTRN FATSecCntInMem :DWORD
;Pointers
EXTRN SysSiz :DWORD
EXTRN BioSiz :DWORD
EXTRN Msg_Allocation_Unit_Val :DWORD
EXTRN FatSpace :DWORD
EXTRN FatSector :DWORD
;Structures
EXTRN DeviceParameters :BYTE
EXTRN IsExtRAWIODrv :BYTE
EXTRN FormatPacket :BYTE
EXTRN Read_Write_Relative :BYTE
RWPacket a_TrackReadWritePacket <>
ifdef NEC_98
RW_TRF_Area db 2048 dup(0)
else
RW_TRF_Area db 512 dup(0)
endif
fLastChance db FALSE ; Flags reinvocation from
; LastChanceToSaveIt. Used by DskPrm
FormatError db 0
Format_End db FALSE
Track_Action db ? ; Actual operation performed on disk
odd_entry db 1 ; flag for 12-bit FAT entry alignment
entry_offset dw ? ; Offset of entry from start of sector
PercentComplete dw 0FFFFh ; Init non-zero so msg will display
; first time
Fat_Init_Value dw 0 ; initializes the Fat
SysTrks dd ?
Sectors dw ?
CurrentHead dw 0
CurrentCylinder dw 0
Tracks_To_Format dw ?
Track_Count dw ?
CurrentCluster dd ? ; holds the cluster currently being checked
; in QuickFormat
BadClusValue dd ? ; holds FAT entry value for bad cluster
BadClusBitMap dd 0
CurrFATInMemStartSec dd 0
CurrFATInMemSecCnt dd 0
CurrFATInMemStartClus dd 0
FATInMemClusCnt dd 0
DATA ENDS
;===========================================================================
; Executable code segment
;===========================================================================
CODE SEGMENT PUBLIC PARA 'CODE'
ASSUME CS:CODE, DS:DATA, ES:DATA
;===========================================================================
;EXTRNs needed in code segment
;===========================================================================
;Labels
EXTRN FatalExit :NEAR
EXTRN CrLf :NEAR
;Functions
EXTRN DetermineExistingFormatNoMsg :NEAR
EXTRN SetStartSector :NEAR
EXTRN SetfBigFat :NEAR
EXTRN Phase2Initialization :NEAR
EXTRN GetBioSize :NEAR
EXTRN GetDosSize :NEAR
EXTRN GetCmdSize :NEAR
EXTRN LastChanceToSaveIt :NEAR
EXTRN AccessDisk :NEAR
EXTRN Yes? :NEAR
EXTRN ExitProgram :NEAR
EXTRN User_String :NEAR
EXTRN Read_Disk :NEAR
EXTRN Seg_Adj :NEAR
EXTRN IsDblSpaceDisk :NEAR
EXTRN Write_Disk :NEAR
EXTRN ShowFormatSize :NEAR
;Constants
EXTRN EXIT_FATAL :ABS
EXTRN EXIT_NO :ABS
EXTRN EXIT_DRV_NOT_READY :ABS
EXTRN EXIT_WRIT_PROTECT :ABS
EXTRN EXIT_FATAL :ABS
EXTRN EXIT_NO :ABS
;===========================================================================
; Declarations for all publics in this module
;===========================================================================
PUBLIC Disk_Format_Proc
PUBLIC FrmtProb
PUBLIC fLastChance
PUBLIC CurrentHead
PUBLIC CurrentCylinder
PUBLIC Multiply_32_Bits
PUBLIC SetDeviceParameters
PUBLIC PercentComplete
PUBLIC Prompt_User_For_Disk
PUBLIC calc_sector_and_offset
PUBLIC ReadFatSector
PUBLIC GetSetFatEntry
PUBLIC GetFatSectorEntry
PUBLIC DetermineTrackAction
PUBLIC QuickFormat
PUBLIC FlushFATBuf
PUBLIC Fat_Init
PUBLIC Get_Bad_Sector_Hard
PUBLIC Multiply_32_Bits
PUBLIC IsThisClusterBad
PUBLIC WrtEOFMrkInRootClus
;========================================================================
;
; DISK_FORMAT_PROC : This procedure is used to call
; the real DiskFormat procedure.
; Returns : NC --> Format successful
; CY --> Format unsuccessful, go to next disk
;
;========================================================================
Disk_Format_Proc proc near
call DetermineTrackAction ; Check for safe format, and validity
; of quick format switch
call init_fat_with_header ; setup blank FAT image
test SwitchMap,SWITCH_Q ; Check for quick format
jz RegularFormat
test SwitchMap,SWITCH_Z ; Check for sec/clus override
jnz RegularFormat
call ShowFormatSize ; size being formatted message
call QuickFormat
jc FarExit ; procedure exit is too far for direct jump
Message msgFormatComplete
FarExit:
jmp Exit_Disk_Format_Proc
RegularFormat:
test SwitchMap,SWITCH_Z
jnz no_load_old_fat ; don't need to load the old FAT
test SwitchMap2,Switch2_C
jnz no_load_old_fat ; don't need to load the old FAT
call SetUpBadClusTransfer
jnc no_load_old_fat
Message msgInsufficientMemory
stc
jmp short FarExit
no_load_old_fat:
call ShowFormatSize ; size being formatted message
call DiskFormat ; Format the disk
jnc GetTrk ; check for problems
FrmtProb:
test SwitchMap,Switch_Select ; SELECT option?
jnz CheckForMore ; No - display message
Message msgFormatFailure
mov ExitStatus, EXIT_FATAL
CheckForMore:
stc ; Signal error which will be handled
; in main routine (by prompting for
; next disk)
jmp Exit_Disk_Format_Proc
;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 Fmt - can't recover
CMP AX,0 ; Are we finished?
jnz TrkFnd ; No - check error conditions
jmp Exit_Disk_Format_Proc ; Yes
;--------------------------------------------------------------------------
; BUG NOTE: The two sections in "if ibmcopyright..." here and below are
; to correct a bug. If one of the Sectors just above the 32M boundary
; were bad, it thought they were in the system area, and hence that the
; disk was unusable.
;
; PYS: IBMCOPYRIGHT removed
;
;--------------------------------------------------------------------------
TrkFnd:
.386
mov EBX,dword ptr Relative_Sector_Low ; get the sector
cmp EBX,StartSector ; Any sec in the sys area bad?
.8086
jae ClrTest ; MZ 2.26 unsigned compare
Message msgDiskUnusable
jmp FrmtProb ; Bad disk -- try again
ClrTest:
mov Sectors,AX ; Save # sectors on the track
test SwitchMap,SWITCH_S ; If sys requested calc size
jz Bad100
cmp BYTE PTR DblFlg,0 ; Is sys space aready calced?
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.oldBPB.BPB_BytesPerSector
.errnz EDP_BPB NE DP_BPB
.386
movzx eax,ax
add EAX,StartSector
mov SysTrks,EAX ; Space Fat,Dir,and system
; files require
cmpTrks:
mov EBX,dword ptr Relative_Sector_Low ;get the low word of the sector
cmp EBX,SysTrks
.8086
JA Bad100 ; MZ 2.26 unsigned compare
mov ExitStatus, EXIT_FATAL
Message msgNotSystemDisk
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 ;hard disk?
.errnz EDP_DEVICETYPE NE DP_DEVICETYPE
jne $$IF5 ; no
call Get_Bad_Sector_Hard ; see if a sector is bad
jmp SHORT $$EN5
$$IF5:
call Get_Bad_Sector_Floppy ; mark entire track bad
$$EN5:
jmp GetTrk
Exit_Disk_Format_Proc:
ret
Disk_Format_Proc ENDP
;==========================================================================
;
; DetermineTrackAction : This procedure sets the value of
; Track_Action based on the setting of
; SWITCH_U, the unconditional format switch.
; Track_Action is the function that is
; actually performed on each track of the
; disk to be formatted.
;
; Inputs : SwitchMap
; Output : SWITCH_U set - Track_Action = Format and Verify
; SWITCH_U clear - Track_Action = Verify only
;
;==========================================================================
DetermineTrackAction proc near
test SwitchMap,SWITCH_U
jz Verify_Only
Format_And_Verify:
mov Track_Action,FORMAT_TRACK ; regular format
ret
Verify_Only:
mov Track_Action,VERIFY_TRACK ; safe format
ret
DetermineTrackAction 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:
; current track = first
; while not done
; if format track fails
; DiskFormatErrors = true
; return
; next track
; =========================================================================
DiskFormat proc near
mov DeviceParameters.DP_SpecialFunctions, (INSTALL_FAKE_BPB or TRACKLAYOUT_IS_GOOD)
.errnz EDP_SPECIALFUNCTIONS NE DP_SPECIALFUNCTIONS
lea DX, DeviceParameters
call SetDeviceParameters
test SwitchMap,switch_8 ; DCL 5/12/86 avoid Naples AH=18h
jnz stdBpB ; lackof support for 8 Secs/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)
; jz StdBPB
; THEN check if
; supported
; Check to see if device driver can handle specified parameters
mov FormatPacket.FP_SpecialFunctions, Status_FOR_FORMAT
mov AX, (IOCTL shl 8) or GENERIC_IOCTL
mov BL, DriveToFormat
inc BL
mov CX, (RAWIO shl 8) or FORMAT_TRACK
cmp IsEXTRAWIODrv,0
je DoFrmt
mov CX, (EXTRAWIO shl 8) or FORMAT_TRACK
DoFrmt:
lea DX, FormatPacket
int 21h
;;%out FORQUICK ENABLED!!!!!
;; clc ;**ARR
; 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 ; 0 --> Can support
je NTSupported
cmp FormatPacket.FP_SpecialFunctions,2 ; 2 --> Cannot support
jne $$IF28
Message msgParametersNotSupportedByDrive
mov Fatal_Error,Yes ; Indicate quittin'type err!
jmp SHORT $$EN28
$$IF28:
cmp FormatPacket.FP_SpecialFunctions,3 ; 3 --> No disk in drive
jne $$IF30
mov AX,Error_Not_Ready ; flag not ready
call CheckError ; set error level
jmp FrmtProb ; exit program
jmp SHORT $$EN30 ; DCL No ROM support is okay
$$IF30:
; except for /N: & /T:
test SwitchMap, SWITCH_N or SWITCH_T ; DCL 5/12/86
jz $$IF32
Message msgParametersNotSupported
mov Fatal_Error,Yes ; Indicate quittin 'type err!
$$IF32:
$$EN30:
$$EN28:
cmp Fatal_Error,Yes
jne StdBPB
jmp FatalExit
; We have the support to carry
; out the FORMAT
NTSupported:
StdBPB:
mov FormatPacket.FP_SpecialFunctions, 0
mov AX, FirstHead
mov FormatPacket.FP_Head, AX
mov AX, FirstCylinder
mov FormatPacket.FP_Cylinder, AX
;M018 - begin
mov AX, word ptr TracksPerDisk
mov word ptr TracksLeft, AX
mov AX, word ptr TracksPerDisk+2
mov word ptr TracksLeft+2, AX
;M018 - end
mov Format_End,False ; flag not at end of format
call Calc_MAX_Tracks_To_Format ; Max track count for
; FormatTrack call
FormatLoop:
call Format_Loop ; Format until CY occurs
cmp Format_End,True ; End of Format?
jne $$IF36
mov FormatError,0 ; signal good format
clc ; clear CY
jmp SHORT $$EN36 ; bad format
$$IF36:
call CheckError ; determine type of error
jc $$IF38
call LastChanceToSaveIt ; acceptable error?
jnc $$IF39 ; yes
mov FormatError,1 ; signal error type
clc ; clear CY
jmp SHORT $$EN39 ; not acceptable error
$$IF39:
call SetStartSector ; start from scratch
call SetfBigFat
push AX
call Phase2Initialization
clc
pop AX
jmp DiskFormat ; try again
$$EN39:
$$IF38:
$$EN36:
return
FormatDone:
mov FormatError,0
clc
return
DiskFormat endp
;=========================================================================
; 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
;
; Assumes: nothing
;
;=========================================================================
Fat_Init PROC NEAR
push ds
push ES
push DI
push AX
push BX
push CX
mov ax,DATA
mov ds,ax
les di,FatSpace
mov BX,Paras_Per_Fat ; Get number of paras
mov AX,Fat_init_value
push DX
mov DX,ES ; Grab ES into DX
$$DO87:
cmp BX,0 ; do while BX not = 0
je $$EN87 ; exit if 0
mov CX,08h ; Word store of paragraph
rep stosw ; Move the data to Fat
xor DI,DI ; Offset always init to 0
inc DX ; Next paragraph
mov ES,DX ; Put next para in ES
dec BX ; Loop iteration counter
jmp SHORT $$DO87
$$EN87:
pop DX
pop CX
pop BX
pop AX
pop DI
pop ES
pop ds
ret
Fat_Init ENDP
;=========================================================================
; SetDeviceParameters:
; Set the device parameters
;
; Input:
; Drive
; DS:DX - pointer to device parameters
;=========================================================================
SetDeviceParameters proc near
mov CX, (EXTRAWIO shl 8) or SET_DEVICE_PARAMETERS
cmp IsEXTRAWIODrv,0
jne DoIoctl
mov CX, (RAWIO shl 8) or SET_DEVICE_PARAMETERS
DoIoctl:
mov AX, (IOCTL shl 8) or GENERIC_IOCTL
mov bl, DriveToFormat
inc bl
int 21H
return
SetDeviceParameters endp
;=========================================================================
; 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
push AX
test SwitchMap, (SWITCH_Backup or SWITCH_Select or SWITCH_AUTOTEST)
jnz $$IF186
ifdef NEC_98
test SwitchMap2,SWITCH2_P
jnz $$IF188
endif
call DskPrm ; prompt user for disk
$$IF186:
test SwitchMap, (Switch_Select) ; /SELECT requested?
jz $$IF188
mov AL, DriveToFormat ; get drv to access for format
call AccessDisk ; access the disk
mov AX,Select_Disk_Message ; display disk prompt
int 2fh ; through int 2fh services
$$IF188:
pop AX
ret
Prompt_User_For_Disk ENDP
;==========================================================================
; 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 PROC NEAR
cmp fLastChance,TRUE
je PrmptRet
cmp DeviceParameters.DP_DeviceType, DEV_HARDDISK
.errnz EDP_DEVICETYPE NE DP_DEVICETYPE
jne GoPrnIt
; DblSpaced floppies return DEV_HARDDISK to the GetDeviceParameters
; call. If this is a DblSpaced drive, go make some additional checks
; before putting out the hard disk warning.
mov al, DriveToFormat
call IsDblSpaceDisk ; sets Z flag if NOT dblspaced disk
jnz MaybeDblSpace
RealHardDisk:
test DeviceParameters.DP_DeviceAttributes, 1
.errnz EDP_DEVICEATTRIBUTES NE DP_DEVICEATTRIBUTES
jnz non_rem
Message msgDiskWarning
jmp short ask_yes
non_rem:
ifndef OPKBLD
Message msgHardDiskWarning
endif ;OPKBLD
ask_yes:
ifndef OPKBLD
call Yes?
pushf
Message msgCrlf
popf
else
clc
endif ;OPKBLD
jnc OkToFormatHardDisk
mov ExitStatus, EXIT_NO
jmp ExitProgram
OkToFormatHardDisk:
call CrLf
call CrLf
return
; Got a DblSpaced drive--see if it's removable or not.
MaybeDblSpace:
mov AX, (IOCTL shl 8) or IOCTL_CHANGEABLE?
mov bl, DriveToFormat
inc bl
int 21H
jc RealHardDisk ; should not happen, but if it does...
or ax, ax ; AX=0 if not removable--quietly exit
jnz PrmptRet ; in this case, later checks will
; stop the format process
GoPrnIt:
mov AL, DriveToFormat
call AccessDisk
Message msgInsertDisk
Message ContinueMsg
call USER_STRING ; Wait for any key
call CrLf
call CrLf
PrmptRet:
mov fLastChance, FALSE
ret
DskPrm 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 ; SELECT option?
jnz $$IF56 ; no - display messages
Message msgCrLf
Message msgCrLf
Extended_Message
jmp SHORT $$EN56 ; yes - set error level
$$IF56:
mov ExitStatus,EXIT_WRIT_PROTECT ; signal write protect error
$$EN56:
stc ; signal Fatal error
ret ; return to caller
NotReadyError:
test SwitchMap,Switch_SELECT ; SELECT option?
jnz $$IF59 ; no - display messages
Message msgCrLf
Message msgCrLf
Extended_Message
jmp SHORT $$EN59 ; yes - set error level
$$IF59:
mov ExitStatus,EXIT_DRV_NOT_READY ;signal Drive not ready
$$EN59:
stc
ret
BadTrackZero:
Message msgDiskUnusable
stc
ret
CheckError endp
;=========================================================================
;
; 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 ; Save regs
push BX
push DX
mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
mov BX,DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
.errnz EDP_BPB NE DP_BPB
xor DX,DX
mul BX ; Get total byte count
mov BX,AX ; Put count in BX
mov ax, 1
or dx, dx
jnz cmttf_onetrack
mov AX,MAX_Format_Size ; Max bytes to format
div BX ; Get track count
cmttf_onetrack:
mov Track_Count,AX
pop DX
pop BX
pop AX
ret
Calc_Max_Tracks_To_Format ENDP
;=========================================================================
; 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
clc ; Initialize to NC
$$DO173: ; While NC
jc $$EN173 ; Exit on CY
call Calc_Current_Head_Cyl ; Head and cylinder calc.
call Determine_Format_Type ; Floppy/hard media?
call Determine_Track_Count ; How many tracks?
call FormatTrack ; Format track(s)
jnc $$IF175 ; Formattrack failed
pushf ; Save flags
cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ; Harddisk?
.errnz EDP_DEVICETYPE NE DP_DEVICETYPE
jne $$IF176
popf ; Restore flags
call Format_Track_Retry ; Find failing track
jmp SHORT $$EN176
$$IF176:
popf ; Restore flags
$$EN176:
$$IF175:
jnc $$IF180 ; Format error?
pushf ; Yes - save flags
push AX ; Save return code
call CheckRealErrors ; Check error type
jc $$IF181 ; If non-Fatal
call DisplayCurrentTrack ; Display % formatted
$$IF181:
pop AX ; Restore regs
popf
$$IF180:
jc $$EN173 ; Exit on CY
call DisplayCurrentTrack ; Tell how much formatted
call Adj_Track_Count ; Decrease track counter
call NextTrack ; Adjust head and cylinder
jmp SHORT $$DO173
$$EN173:
ret
Format_Loop ENDP
;=========================================================================
; 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
push CX ; save CX
mov CX,FormatPacket.FP_Cylinder ; get current cylinder
mov CurrentCylinder,CX ; put into variable
mov CX,FormatPacket.FP_Head ; get current head
mov CurrentHead,CX ; put into variable
pop CX ; restore CX
ret
Calc_Current_Head_Cyl endp
; =========================================================================
; 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
cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ;harddisk?
.errnz EDP_DEVICETYPE NE DP_DEVICETYPE
jne $$IF158
; Set for multi track format
mov FormatPacket.FP_SpecialFunctions,Multi_Track_Format
jmp SHORT $$EN158
$$IF158: ; Set for single track format
mov FormatPacket.FP_SpecialFunctions,Single_Track_Format
$$EN158:
ret
Determine_Format_Type ENDP
;=========================================================================
;
; 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
; Harddisk?
cmp DeviceParameters.DP_DeviceType,Dev_HardDisk
.errnz EDP_DEVICETYPE NE DP_DEVICETYPE
jne $$IF163
call Calc_Track_Count ; Calc Tracks_To_Format
jmp SHORT $$EN163 ; Removable media
$$IF163:
mov Tracks_To_Format,0001h ; Default to 1 track
$$EN163:
ret
Determine_Track_Count ENDP
;=========================================================================
;
; 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
push AX ; Save regs
mov AX,Track_Count ; Max bytes to format
cmp word ptr TracksLeft+2,0 ; M018; More than 64K of tracks?
jnz $$IF166 ; M018; Then surely use Track_Count
cmp AX,word ptr TracksLeft ; M018; Too many tracks?
JNA $$IF166
mov AX,word ptr TracksLeft ; M018; Format remaining tracks
$$IF166:
mov Tracks_To_Format,AX ; Save track count
pop AX
ret
Calc_Track_Count ENDP
;=========================================================================
; 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
mov AX,(IOCTL shl 8) or Generic_IOCTL
mov BL,DriveToFormat ; Get Drive number
inc BL ; Make it 1 based
mov CX,(RawIO shl 8)
cmp IsEXTRAWIODrv,0
je DoFrmt2
mov CX,(EXTRawIO shl 8)
DoFrmt2:
or CL,Track_Action ; Track_Action is either
; Format and Verify, or
; Verify only
mov DX,Tracks_To_Format ; Get track count
mov FormatPacket.FP_TrackCount,DX ; Put count in parms list
lea DX,FormatPacket ; Ptr to parms
int 21h
;;%out FORQUICK ENABLED!!!!!
;; clc ;;** ARR
jnc FormatTrackExit ; Error?
mov AH,59h ; Get extended error
xor BX,BX ; Clear BX
int 21h
cmp AX,67 ; Induced error from ENHDISK?
jne notInducedError
clc
ret
notInducedError:
stc ; Flag an error
FormatTrackExit:
ret
FormatTrack 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 ; Clear existing CY
mov Tracks_To_Format,1 ; Only format 1 track
$$DO168: ; While we have good tracks
jc $$EN168 ; Exit on bad track
call FormatTrack ; Format the track
jc $$IF170 ; Error?
call DisplayCurrentTrack ; Adjust percent counter
call Adj_Track_Count
call NextTrack ; Calc next track
$$IF170:
jmp SHORT $$DO168
$$EN168:
ret
Format_Track_Retry ENDP
;=========================================================================
;
; DisplayCurrentTrack : This procedure prints the percentage of disk
; formatted so far.
; If /select is present, format can be exited
; by returning AX!=0 from the int 2fh call, which
; is handled by install. This is to permit the
; user to stop the format in progress.
;
;===========================================================================
DisplayCurrentTrack proc near
push DX
push CX
push AX
push DI ; M018
push SI ; M018
mov AX,Tracks_To_Format ;get track count
add Formatted_Tracks_Low,AX ;Indicate formatted a track
adc Formatted_Tracks_High,0
mov AX,Formatted_Tracks_Low
mov BX,Formatted_Tracks_High
mov CX,100 ;Make integer calc for div
call Multiply_32_Bits ; BX:AX = (Cyl * Head *100)
mov DX,BX ;Set up divide
; DX:AX: 100*head*cylinder (should not be bigger than a DWORD)
; DI:SI: heads*cylinder
; We need to assure a word division
mov DI,word ptr TracksPerDisk+2
mov SI,word ptr TracksPerDisk
SetUpDivide:
or DI,DI
jz DivideOK
shr DI,1 ; shift DI:SI 1 bit right
rcr SI,1
shr DX,1 ; shift DX:AX 1 bit right
rcr AX,1
jmp short SetUpDivide
DivideOk:
div SI
cmp AX,PercentComplete ;Only print message when change
je ScreenUpdateDone
; johnhe 02-27-90
; Change added here for DOS 5.0 install program to do a
; special interrupt to display the percent complete on
; a gage. AX == special code, BX == percent complete
test SwitchMap,Switch_Select ; Was format spawned by the
jz NormalDisplay ; install program?
mov BX,AX ; BX == percent completed
mov AX,GAGE_UPDATE ; AX == special function code
clc
int 2fh ; Multiplex interrupt
or AX,AX ; AX <> 0 --> user wants to exit
jz ScreenUpdateDone
jmp FatalExit
; End of code added for DOS 5.0 install program
NormalDisplay:
mov PercentComplete,AX ; Save it if changed
Message msgCurrentTrack
ScreenUpdateDone:
pop SI ; M018
pop DI ; M018
pop AX
pop CX ; Restore register
pop DX
return
DisplayCurrentTrack endp
;=========================================================================
; 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
push AX ; save regs
push DX ; M018
mov DX,word ptr TracksLeft+2; get tracks remaining
mov AX,word ptr TracksLeft
sub AX,Tracks_To_Format ; subtract amount formatted
sbb DX,0
mov word ptr TracksLeft,AX ; save new tracks remaining value
mov word ptr TracksLeft+2,DX
pop DX ; M018
pop AX ; restore regs
ret
Adj_Track_Count endp
;=========================================================================
;
; 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
mov CX,word ptr TracksLeft+2
or CX,Word ptr TracksLeft
jne $$IF149 ; Yes
stc ; Signal end of format
mov Format_End,True
jmp SHORT $$EN149
$$IF149:
mov CX,Tracks_To_Format ; Get mAX track count for call
$$DO151: ; While tracks remain
cmp CX,00 ; End of head/cyl. adjustment?
je $$EN151 ; Yes
inc FormatPacket.FP_Head ; Next head
mov AX,FormatPacket.FP_Head ; Get head for comp
cmp AX,DeviceParameters.DP_BPB.oldBPB.BPB_Heads ; Exceeded head count?
.errnz EDP_BPB NE DP_BPB
jne $$IF154 ; Yes
mov FormatPacket.FP_Head,00 ; Reinit. head
inc FormatPacket.FP_Cylinder ; Next cylinder
$$IF154:
dec CX ; Decrease counter
jmp SHORT $$DO151
$$EN151:
clc ; Clear CY
$$EN149:
ret
NextTrack 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 ; Save regs
push BX
push DX
.386
mov EAX, TracksPerDisk
sub EAX, TracksLeft
movzx ebx, DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
.errnz EDP_BPB NE DP_BPB
mul ebx
mov dword ptr Relative_Sector_Low,EAX ; Save sector #
.8086
pop DX ; Restore regs
pop BX
pop AX
return
CurrentLogicalSector 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 format
; /c was given
test FormatError, 0ffH
jz ContinueFormat
mov FormatError, 0
jmp SHORT ReportBadTrack
ContinueFormat:
call Adj_Track_Count ; Decrease track counter
call NextTrack ; Adjust head and cylinder
cmp Format_End,True ; End of format?
je $$IF44 ; No
call Format_Loop ; Format until CY
cmp Format_End,True ; End of format?
je $$IF45 ; No
call CheckError ; Must be error - which error?
jc $$IF46 ; Non-Fatal error?
call CurrentLogicalSector ; Yes - get position
; set tracksize
mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
.errnz EDP_BPB NE DP_BPB
clc ; Signal O.K. to continue
$$IF46:
jmp SHORT $$EN45
$$IF45:
jmp SHORT NoMoreTracks ;End of format
$$EN45:
jmp SHORT $$EN44
$$IF44:
jmp SHORT NoMoreTracks ; end of format
$$EN44:
return
ReportBadTrack:
call CurrentLogicalSector
mov AX, DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
clc
return
NoMoreTracks: ; Don't display done msg
test SwitchMap,(Switch_Select or SWITCH_AUTOtest)
jnz $$IF52 ; if EXEC'd by SELECT
Message msgFormatComplete
$$IF52:
mov AX, 0
clc
return
BadSector endp
;=========================================================================
; 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
;
; ClustBound_Adj_Factor - The number of Sectors
; that are to be read
; at one time.
; ClustBound_SPT_Count - Used by Calc_Cluster_Boundary
; to track how many Sectors
; have been read.
; ClustBound_Flag - True (Use cluster buffer)
; - False (Use internal buffer)
; ClustBound_Buffer_Seg - Segment of buffer
;
; Outputs : Marked cluster as bad
;=========================================================================
Procedure Get_Bad_Sector_Hard
push CX ; Save CX
mov CX,0001h ; Set counter to start at 1
mov ClustBound_SPT_Count,00h ; Clear sector counter
mov ClustBound_Adj_Factor,01h ; Default value
; DO WHILE Sectors left
$$DO115:
cmp CX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack ;At end?
.errnz EDP_BPB NE DP_BPB
ja $$EN115 ; Yes,exit
push CX ; Save CX
cmp ClustBound_Flag,True ; Full buffer there?
jne $$IF117 ; Yes
call Calc_ClustBound_ ; See if on boundary
mov AX,ClustBound_Buffer_Seg
; Point to transfer area
mov WORD PTR RWPacket.TRWP_Transferaddress[0],0
mov WORD PTR RWPacket.TRWP_Transferaddress[2],AX
jmp SHORT $$EN117 ; Default to internal buffer
$$IF117: ; Point to transfer area
mov WORD PTR RWPacket.TRWP_Transferaddress[0],offset RW_TRF_Area
mov WORD PTR RWPacket.TRWP_Transferaddress[2],DS
$$EN117:
call Verify_Structure_Set_Up ; Set up verify vars
mov AX,(IOCTL shl 8) or GENERIC_IOCTL
xor BX,BX ; Clear BX
mov BL,DriveToFormat ; Get Drive
inc BL ; Adjust it
mov CX,(IOC_DC shl 8) or READ_TRACK
cmp IsEXTRAWIODrv,0
je DoIOCTL2
mov CX,(IOC_EDC shl 8) or READ_TRACK
; Buffer is only cluster size
DoIOCTL2:
lea DX,RWPacket ; Point to parms
int 21h
pop CX ; Restore CX
push CX ; Save CX
jnc $$IF120 ; An error occurred
call Calc_Cluster_Position ; Determine which cluster
call BadClus ; Mark the cluster as bad
$$IF120:
pop CX
add CX,ClustBound_Adj_Factor ; Adjust loop counter
mov AX,ClustBound_Adj_Factor ; Get adjustment factor
xor DX,DX
add AX,Relative_Sector_Low ; Add in low word
adc DX,Relative_Sector_High ; Pick up carry in high word
mov Relative_Sector_Low,AX ; Save low word
mov Relative_Sector_High,DX ; Save high word
jmp SHORT $$DO115
$$EN115:
pop CX
ret
Get_Bad_Sector_Hard ENDP
;=========================================================================
; 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
push BX ; Save regs
push CX
; Get Sectors/track
mov CX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
.errnz EDP_BPB NE DP_BPB
$$DO123: ; While Sectors left
cmp CX,00 ; At end
je $$EN123 ; Yes
push BX ; Save BX we destroy it
push CX ; Save CX we destroy it
call Calc_Cluster_Position ; Get cluster position
call BadClus ; Mark it as bad
pop CX ; Restore regs
pop BX
dec CX ; Decrease loop counter
.386
inc dword ptr Relative_Sector_Low ; Next sector
.8086
jmp SHORT $$DO123
$$EN123:
pop CX ; Restore regs
pop BX
ret
Get_Bad_Sector_Floppy ENDP
;=========================================================================
;
; Inputs: DX:AX - 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
;
; 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 ; mark bad clusters
push DI ; save affected regs
push AX
push BX
push CX
push DX
push ES
cmp FATNotAllInMem,0
je DoBadInMem
push dx ; Save cluster number
push ax
call AllocInitBadClusBitmap ; Does nothing if BadClusBitmap
; already exists
.386
;; Manual assemble to prevent compile warning
;; pop eax ; recover cluster #
db 066h,058h
;;
jc $$EN10
push ds
push si
lds si,BadClusBitMap
mov ebx,eax
shr ebx,19 ; (E)BX is "64k index" of this bit
and eax,00007FFFFh ; bit index in that 64k
mov cx,ds
add cx,bx ; Go to correct 64k piece
mov ds,cx
bts dword ptr [si],eax ; Set the bit
pop si
pop ds
jnc short ClrZr
xor ax,ax ; Set zero flag, cluster already marked
jmp $$EN10
ClrZr:
inc eax ; Clear the zero flag
.8086
jmp $$EN10
DoBadInMem:
mov ES, WORD PTR FatSpace + 2 ; obtain seg of Fat
cmp fBig32Fat,TRUE ; 32 bit Fat?
je $$IF8a ; yes
cmp fBigFat,TRUE ; 16 bit Fat?
je $$IF8 ; yes
; 12-bit FAT
mov CX,2 ; divide by 2
push AX ; saves low cluster number
mov SI,DX ; pick up high word of cluster
mov DI,AX ; pick up low word of cluster
call divide_32_Bits ; 32 bit divide
add AX,DI ; add in low word of result
adc DX,SI ; pick up low word carry
; cluster = cluster * 1.5
add AX,WORD PTR FatSpace ; add 0
adc DX,0 ; pick up carry
mov BX,DX ; get high word for adjust
mov CX,ES ; place seg in AX
call BadClus_address_Adjust ; adjust segment offset
mov ES,CX ; new segment
mov SI,AX ; new offset
mov DX,0ff7h ; bad cluster flag
mov AX,0fffh ; mask value
pop CX ; restore AX in CX - low cluster #
test CX,1 ; is old clus num odd?
jz $$IF9 ; yes
.386
shl AX,4 ; get only 12 bits - fff0
shl DX,4 ; get 12 bits - ff70
.8086
$$IF9:
jmp SHORT $$EN8
$$IF8a:
; 32-bit FAT
xor SI,SI ; clear si
mov BX,DX ; get high word for multiply
mov CX,4 ; multiply by 4
call Multiply_32_Bits ; 32 bit multiply due to 4 bytes per
; Fat cell. This gives us an offset
; into the FAT
mov CX,ES ; place seg in CX
call BadClus_Address_Adjust ; adjust segment:offset
mov ES,CX ; new segment
mov SI,AX ; new offset
.386
mov ecx,dword ptr ES:[SI] ; Get previous value
and ecx,00FFFFFFFh ; Discard high 4 bits
mov edx,00ffffff7h
mov dword ptr ES:[SI],edx ; flag it a bad cluster
cmp EDX,ECX ; return op == badval;
.8086
jmp short $$EN10
$$IF8:
; 16-bit FAT
xor SI,SI ; clear si
mov BX,DX ; get high word for multiply
mov CX,2 ; multiply by 2
call Multiply_32_Bits ; 32 bit multiply due to 2 bytes per
; Fat cell. This gives us an offset
; into the FAT
mov CX,ES ; place seg in CX
call BadClus_Address_Adjust ; adjust segment:offset
mov ES,CX ; new segment
mov SI,AX ; new offset
mov DX,0fff7h ; bad cluster value
mov AX,0ffffh ; mask value
$$EN8:
mov CX,ES:[SI] ; get contents of Fat cell
and CX,AX ; make it 12 or 16 bit
; depending on value in AX
not AX ; set AX to 0
and ES:[SI],AX ; clear Fat entry
or ES:[SI],DX ; flag it a bad cluster
cmp DX,CX ; return op == badval;
$$EN10:
pop ES
pop DX
pop CX
pop BX
pop AX
pop DI
return
badclus endp
;=========================================================================
; 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 ; Set up verify structure
mov RWPacket.TRWP_SpecialFunctions,00h ; Reset special functions
mov AX,FormatPacket.FP_Head ; Get current head
mov RWPacket.TRWP_Head,AX ; Get current head
mov AX,FormatPacket.FP_Cylinder ; Get current cylinder
mov RWPacket.TRWP_Cylinder,AX ; Get current cylinder
dec CX ; Make sector 0 based
mov RWPacket.TRWP_FirstSector,CX ; Get sector to read
mov AX,ClustBound_Adj_Factor ; Get # of Sectors to read
mov RWPacket.TRWP_SectorsToReadWrite,AX ; Read only # sector(s)
call Calc_Cluster_Position ; Determine cluster number
mov WORD PTR Msg_Allocation_Unit_Val[+2],DX ; Save high word of cluster
mov WORD PTR Msg_Allocation_Unit_Val[+0],AX ; Save low word of cluster
message msgVerify
ret
Verify_Structure_Set_Up ENDP
;=========================================================================
; 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 number
;=========================================================================
Procedure Calc_Cluster_Position
push CX ; Save regs
push DI
push SI
mov DX,WORD PTR Relative_Sector_High ; Get the high sector word
mov AX,WORD PTR Relative_Sector_Low ; Get the low sector word
sub AX,word ptr StartSector ; Get relative sector #
sbb DX,word ptr StartSector+2 ; Pick up borrow
mov SI,DX ; Get high word
mov DI,AX ; Get low word
xor CX,CX ; Clear CX
; Get Sectors/cluster
mov CL,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
.errnz EDP_BPB NE DP_BPB
call divide_32_Bits ; 32 bit division
mov DX,SI ; Get high word of result
mov AX,DI ; Get low word of result
add AX,2 ; Adjust for cluster bias
adc DX,0 ; Pick up carry
pop SI ; Restore regs
pop DI
pop CX
ret
Calc_Cluster_Position ENDP
;=========================================================================
; Calc_ClustBound_ : This routine will determine where, within a
; cluster, a sector resides.
;
; Inputs : Relative_Sector_Low - Sector
; Relative_Sector_High
;
; Outputs : ClustBound_Adj_Factor - The number of Sectors
; remaining in the cluster.
; ClustBound_SPT_Count - The count of Sectors
; having been accessed for
; a track.
;=========================================================================
Procedure Calc_ClustBound_
push AX ; Save regs
push BX
push CX
push DX
push SI
push DI
xor DX,DX ; Clear high word
mov DX,WORD PTR Relative_Sector_High
mov AX,WORD PTR Relative_Sector_Low
sub AX,word ptr StartSector ; Get relative sector #
sbb DX,word ptr StartSector+2 ; Pick up borrow
mov SI,DX ; Get high word
mov DI,AX ; Get low word
xor CX,CX ; Clear CX
mov CL,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
.errnz EDP_BPB NE DP_BPB
call divide_32_Bits ; 32 bit division
or CX,CX ; See if remainder exists
jz $$IF132 ; Remainder exists
xor BX,BX
mov BL,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
sub BX,CX
mov ClustBound_Adj_Factor,BX ; Remainder = sector count
jmp SHORT $$EN132 ; Noremainder
$$IF132:
xor BX,BX ; Clear BX
mov BL,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
mov ClustBound_Adj_Factor,BX
$$EN132:
mov AX,ClustBound_SPT_Count ; Get current sector count
xor DX,DX ; Clear high word
add AX,ClustBound_Adj_Factor ; Get next sector count
; Exceeded Sectors/track?
cmp AX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
jna $$IF135 ; Yes
; only use difference
mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
sub AX,ClustBound_SPT_Count ; Get next sector count
mov ClustBound_Adj_Factor,AX
$$IF135:
mov AX,ClustBound_SPT_Count ; Get sector count
xor DX,DX ; Clear high word
add AX,ClustBound_Adj_Factor ; Get new sector count
mov ClustBound_SPT_Count,AX ; Save it
pop DI ; Restore regs
pop SI
pop DX
pop CX
pop BX
pop AX
ret
Calc_ClustBound_ ENDP
;=========================================================================
;
; 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
push BX ; Save regs
push DX
push DI
push SI
mov DX,CX ; Save segment value
mov SI,BX ; Get high word for divide
mov DI,AX ; Get low word for divide
xor CX,CX ; Clear CX
mov CL,Paragraph_Size ; Divide by 16
call divide_32_Bits ; Perform division
add DX,DI ; Adjust segment for result
mov AX,CX ; Pick up the remainder
mov CX,DX ; Pass back new segment
pop SI ; Restore regs
pop DI
pop DX
pop BX
ret
BadClus_address_Adjust 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
;
;=========================================================================
Multiply_32_Bits PROC
.386
push ax
mov ax,bx
shl eax,16
pop ax
movzx ecx,cx
mul ecx
mov ebx,eax
shr ebx,16
or edx,edx ; Overflow?
jz short OkRet ; No, carry clear
stc
OkRet:
.8086
ret
Multiply_32_Bits endp
;=========================================================================
; divide_32_Bits - This routine will perform 32bit division
; It works by first dividing the high word
; and leaving the remainder in DX and then
; dividing the low word with the remainder
; still in DX
;
; Inputs : SI:DI - value to be divided
; CX - divisor
;
; Outputs : SI:DI - result
; CX - remainder
;=========================================================================
Procedure divide_32_Bits
push AX ; Save regs
push BX
push DX
xor DX,DX ; clear DX
mov AX,SI ; get high word
div CX ; get high word result
mov SI,AX ; save high word result
mov AX,DI ; get low word
div CX ; get low word result
mov DI,AX ; save low word result
mov CX,DX ; pick up remainder
pop DX ; restore regs
pop BX
pop AX
ret
divide_32_Bits endp
;=========================================================================
;
; QuickFormat : This procedure will perform a Quick format by
; simply copying any bad cluster markers from the
; old FAT on the disk to the new FAT. The old FAT is
; read in one sector at a time using FatSector buffer.
; The new FAT is held in FatSpace buffer.
;
; Registers Destroyed : SI,AX,BX,CX
;
; Assumes: DS:DATA,ES:Nothing
;
;=========================================================================
QuickFormat proc near
mov SI,DATA
mov ES,SI ; Set ES to data segment
assume ES:DATA,DS:Nothing ; Assembler directive
; Set device parameters here
mov ES:DeviceParameters.DP_SpecialFunctions,(INSTALL_FAKE_BPB or TRACKLAYOUT_IS_GOOD)
.errnz EDP_SPECIALFUNCTIONS NE DP_SPECIALFUNCTIONS
lea DX,ES:DeviceParameters
call SetDeviceParameters
.386
mov ES:sector_in_buffer,0ffffffffh ; force first read to ensure
; buffer validity
test ES:fBig32FAT,0ffh ; See if 32 bit fat
jz short Test16BitEntry ; If zero then 16 or 12 bit fat
mov EBX,00ffffff7h ; Set 32 bit value for bad cluster
jmp SHORT InitClusCount
Test16BitEntry:
test ES:fBigFAT,0ffh ; See if 16 bit fat
jz short Set12BitEntry ; If zero then 12 bit fat
mov EBX,0000fff7h ; Set 16 bit value for bad cluster
jmp SHORT InitClusCount
Set12BitEntry:
mov EBX,00000ff7h ; Set 12 bit value for bad cluster
InitClusCount:
mov ES:CurrentCluster,2 ; M015; No need to do the first 2
mov ES:BadClusValue,EBX
cmp es:FATNotAllInMem,0
je short QuickLoop
push ds
push es
pop ds
message msgSetBadClus
pop ds
QuickLoop:
mov EAX,ES:CurrentCluster
call calc_sector_and_offset ; determine location of this entry
mov EBX,ES:sector_in_buffer
mov EAX,ES:sector_to_read
cmp EAX,EBX ; check if required sector is in buffer
je short DontHaveToRead
cmp es:FATNotAllInMem,0
je short DoRead
push ds
push es
pop ds
call DisplayFatDonePcnt
pop ds
DoRead:
call ReadFatSector ; read a sector of the FAT into buffer
jc ExitQuickFormatCRLFErr ; check for error
DontHaveToRead:
mov EAX,ES:CurrentCluster ; EAX = current cluster
xor CX,CX ; ECX = get cluster contents signal
lds SI,ES:FatSector ; DS:SI --> FAT buffer
call GetFatSectorEntry ; EAX = contents of FAT entry
mov EBX,ES:BadClusValue ; Restore bad cluster value
cmp EAX,EBX ; Is this cluster marked bad?
jne short NextCluster ; If EAX<>EBX good cluster
MarkInFormatBuffer:
cmp es:FATNotAllInMem,0
je short DoBadInMem2
push es
pop ds
call AllocInitBadClusBitmap ; Does nothing if BadClusBitmap
; already exists
jc short ExitQuickFormatCRLFErr ; check for error
mov EAX,ES:CurrentCluster ; EAX = current cluster
lds si,es:BadClusBitMap
mov ebx,eax
shr ebx,19 ; (E)BX is "64k index" of this bit
and eax,00007FFFFh ; bit index in that 64k
mov cx,ds
add cx,bx ; Go to correct 64k piece
mov ds,cx
bts dword ptr [si],eax ; Set the bit
jmp short NextCluster
DoBadInMem2:
mov ECX,EBX ; ECX = value to set in FAT buffer
mov EAX,ES:CurrentCluster ; EAX = this cluster number
lds SI,ES:FatSpace ; DS:SI --> Format's FAT buffer
call GetSetFatEntry ; Set the cluster in Format's buffer
NextCluster:
inc ES:CurrentCluster ; go to next cluster
mov EAX,ES:CurrentCluster
mov EBX,ES:TotalClusters
cmp EAX,EBX ; check for last cluster in FAT
jna QuickLoop
.8086
mov BX,DATA
mov DS,BX ; restore DS to DATA segment
assume DS:DATA,ES:DATA ; Assembler directive
cmp ds:FATNotAllInMem,0
je ExitQuickFormatRet ; Carry clear if jmp
message msgSetBadClusDone
clc
ExitQuickFormatRet:
ret
ExitQuickFormatCRLFErr:
mov BX,DATA
mov DS,BX
cmp ds:FATNotAllInMem,0
stc
je ExitQuickFormatRet
Message msgCrLf
stc
jmp short ExitQuickFormatRet
QuickFormat endp
;===========================================================================
;
; calc_sector_and_offset : This procedure computes the logical sector
; number the given FAT entry is in, and its
; offset from the start of the sector.
;
; Inputs : EAX = entry number
; fBigFat = flag for 12- or 16-bit FAT entries
; Number of reserved sectors
;
; Output : sector_to_read = logical disk sector holding FAT entry
; entry_offset = offset from start of sector
; odd_entry = flag for 12-bit entry alignment (1=odd,0=even)
;
; Registers Destroyed : AX,BX,CX,DX
;
; Strategy : This procedure assumes the sector size is 512 bytes.
; The byte offset from the start of the FAT is first
; calculated. This is then divided by 512, so that
; required sector = quotient
; offset = remainder
; The logical sector number is obtained by adding on the
; number of reserved sectors.
;
; M017: The code does not assume 512 BytesPerSector (it is even simpler!)
;============================================================================
calc_sector_and_offset proc near
assume DS:NOTHING,ES:DATA
.386
xor EDX,EDX
test ES:fBig32Fat,0ffh ; See if 32 bit FAT
jz short TestOffset16 ; If not do 16 or 12 bit FAT
shl EAX,1 ; EAX *= 2
rcl EDX,1
jmp short FindOffset16 ; Now mult by 2 again for * 4
TestOffset16:
test ES:fBigFat,0ffh ; See if 16 bit FAT
jz short FindOffset12 ; If not do 12 bit FAT
FindOffset16:
shl EAX,1 ; EAX *= 2
rcl EDX,1
; Now offset from start of FAT is
; in EDX:EAX
jmp SHORT FindSector
FindOffset12:
mov BX,AX ; BX = cluster number
shl AX,1
add AX,BX ; AX *= 3
mov ES:odd_entry,AL ; lsb of AX determines even or odd
and ES:odd_entry,1
shr AX,1 ; Divide by 2
; Now offset from start of FAT is
; in EDX:EAX
FindSector:
movzx ebx,ES:DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
.errnz EDP_BPB NE DP_BPB
div ebx
mov ES:entry_offset,DX
movzx ebx,ES:DeviceParameters.DP_BPB.oldBPB.BPB_RESERVEDSECTORS
add EAX,ebx
mov ES:sector_to_read,EAX
.8086
ret
calc_sector_and_offset endp
;===========================================================================
;
; ReadFatSector : This procedure will read in a sector of the FAT
; into the FatSector buffer. This is done by loading
; the required parameters and calling ReadWriteSectors.
;
; Input : sector_to_read
; Output: loaded buffer
; sector_in_buffer
;
; Registers destroyed: AX,BX,CX,DX
;
;===========================================================================
ReadFatSector proc near
assume DS:NOTHING,ES:DATA
push DS ; Preserve DS
.386
mov EDX,ES:sector_to_read ; EDX = starting sector
;; Manual assemble to prevent compile warning
;; push edx
db 066h,052h
;;
cmp ES:DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFAT,0
.errnz EDP_BPB NE DP_BPB
je short NotBigFAT1
mov cx,ES:DeviceParameters.DP_BPB.BGBPB_ExtFlags
test cx,BGBPB_F_NoFATMirror
jz short NotBigFAT1
and ecx,NOT BGBPB_F_ActiveFATMsk
jz short NotBigFAT1
mov ebx,edx
mov eax,dword ptr ES:DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
mul ecx
add eax,ebx
mov edx,eax
NotBigFAT1:
mov ebx,edx
shr ebx,16
mov ES:Read_Write_Relative.Start_Sector_High,bx
mov AL,ES:DriveToFormat ; AL = DOS drive number
mov CX,1 ; 1 sector only
lds BX,ES:FatSector ; DS:BX --> read buffer
call Read_Disk ; perform read
;; Manual assemble to prevent compile warning
;; pop edx
db 066h,05Ah
;;
mov ES:sector_in_buffer,EDX ; update sector in memory
.8086
pop DS ; Restore DS
ret
ReadFatSector endp
;=========================================================================
; WriteFatSector : This routine writes the logical sector count requested.
; of the FAT
;
; Inputs : AL - Drive letter
; DS:BX - Segment:offset of transfer address
; ECX - Sector count
; EDX - 1st. sector
; ES -> Data
;
; Outputs : Logical Sectors written
;=========================================================================
procedure WriteFatSector
assume DS:NOTHING,ES:DATA
.386
$$DO67:
or ECX,ECX ; any Sectors?
jz short $$EN67 ; no
ifdef NEC_98
cmp ECX,10h ; Single write?
jna short $$IF69 ; yes
;; Manual assemble to prevent compilke warning
;; push ECX ; save count left
db 066h,051h
;;
mov CX,10h
push AX ; save AX
mov eax,edx
shr eax,16
mov Read_Write_Relative.Start_Sector_High,ax
pop ax ; Recover drive
push ax
;; Manual assemble to prevent compile warning
;; push EDX
db 066h,052h
;;
call write_disk ; write it
;; Manual assemble to prevent compile warning
;; pop EDX
db 066h,05Ah
;;
pop AX ; restore AX
;; Manual assemble to prevent compile warning
;; pop ECX ; restore count
db 066h,059h
;;
jc short Write_Exit ; exit if fail
mov SI,ES:DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
shl SI,1
shl SI,1
shl SI,1
shl SI,1 ; * 10h
call seg_adj ; adjust segment
mov BX,SI ; new offset
add EDX,10h
sub ECX,10h
jmp SHORT $$DO67
else
cmp ECX,40h ; Single write?
jna short $$IF69 ; yes
;; Manual assemble to prevent compilke warning
;; push ECX ; save count left
db 066h,051h
;;
mov CX,40h
push AX ; save AX
mov eax,edx
shr eax,16
mov Read_Write_Relative.Start_Sector_High,ax
pop ax ; Recover drive
push ax
;; Manual assemble to prevent compile warning
;; push EDX
db 066h,052h
;;
call write_disk ; write it
;; Manual assemble to prevent compile warning
;; pop EDX
db 066h,05Ah
;;
pop AX ; restore AX
;; Manual assemble to prevent compile warning
;; pop ECX ; restore count
db 066h,059h
;;
jc short Write_Exit ; exit if fail
mov SI,8000h
call seg_adj ; adjust segment
mov BX,SI ; new offset
add EDX,40h
sub ECX,40h
jmp SHORT $$DO67
endif
$$IF69:
push AX ; save drive
mov eax,edx
shr eax,16
mov Read_Write_Relative.Start_Sector_High,ax
pop ax ; Recover drive
push ax
call write_disk ; write it
pop AX ; restore AX
mov ECX,0 ; set CX to 0 - last read
.8086 ; DO NOT XOR!!!
$$EN67:
Write_Exit:
ret
WriteFatSector ENDP
FlushCurrInMemFATBuf proc near
ASSUME DS:DATA,ES:NOTHING
push ds
push ds
pop es
.386
assume ES:DATA
movzx cx,DeviceParameters.DP_BPB.oldBPB.BPB_NumberOfFats ;loop control
.errnz EDP_BPB NE DP_BPB
or CX,CX ;check for zero
stc
jz short FFMExit
movzx eax,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
or ax,ax
jnz short GtFatSz
mov eax,dword ptr DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
GtFatSz:
mov edx,CurrFATInMemStartSec
lds BX,FatSpace ;DS:BX --> FatSpace
assume DS:NOTHING,ES:DATA
mov SI,BX ;Set up for add. calc
call SEG_ADJ ;Get adjusted seg:off
mov BX,SI ;Get new offset
WriteFatLp: ;loop while FATs > 0
;; Manual assemble to prevent compile warning
;; push eax ;Save FAT size
db 066h,050h
;;
push BX ;save Fat offset
push DS ;save Fat segment
push CX ;save Fat count
;; Manual assemble to prevent compile warning
;; push EDX ;Fat start sector
db 066h,052h
;;
mov ecx,CurrFATInMemSecCnt
mov AL,DriveToFormat
call WriteFatSector ;write the Fat
;; Manual assemble to prevent compile warning
;; pop EDX ;get 1st. Fat sector
db 066h,05Ah
;;
pop CX ;get Fat count
pop DS ;restore Fat segment
pop BX ;restore Fat offset
;; Manual assemble to prevent compile warning
;; pop eax ;restore FAT size
db 066h,058h
;;
jc short FFMExit ;check for errors
add EDX,EAX ;next FAT start sector
loop WriteFatLp ;write all FATs
clc
FFMExit:
pop ds
ret
FlushCurrInMemFATBuf endp
DisplayFatDonePcnt proc near
assume DS:DATA,ES:NOTHING
.386
mov eax,CurrentCluster
dec eax
dec eax
mov ecx,100
mul ecx
mov ecx,TotalClusters
dec ecx
dec ecx
div ecx
.8086
cmp ax,100
jbe PcntOk
mov ax,100
PcntOk:
cmp AX,PercentComplete ;Only print message when change
je NoUpd
mov PercentComplete,AX ; Save it if changed
Message msgCurrentTrack
NoUpd:
ret
DisplayFatDonePcnt endp
;===========================================================================
; Routine name: FlushFATBuf
;===========================================================================
;
; Description: Flush the in memory FAT buffer out to the disk
;
; Arguments: None
; ----------------------------------------------------------------
; Returns: carry set if error
; -----------------------------------------------------
; Registers destroyed: EAX EBX ECX EDX
; ----------------------------------------
; Strategy
; --------
;===========================================================================
FlushFATBuf PROC near
assume DS:DATA,ES:NOTHING
push DS ;preserve DS
cmp FATNotAllInMem,0
.386
je WrtWholeFat
;
; What we have at this point is the first part of the FAT in the in
; memory FAT buf and the BadClusBitMap which indicates what clusters
; we want to mark bad.
;
; Go through the in memory FAT buf (currently first FATSecCntInMem
; sectors of the FAT) marking any bad clusters, and/or write an EOF
; mark in the root directory start cluster, write it out.
;
; For rest of FAT, zero init in memory FAT buf, mark bad clusters
; and/or put EOF mark in root directory start cluster and write it out.
;
; We had better be talking 32-bit FAT here!!!!!! 12-bit and 16-bit
; FATs always fit in memory.
;
test fBig32FAT,0ffh
stc ; Set error
jz ExitWriteFat ; Not 32-bit FAT !!!?????
; Set the bad clus value
mov BadClusValue,00ffffff7h ; Set 32 bit value for bad cluster
; Set the current in mem FAT start sector
movzx eax,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors
.errnz EDP_BPB NE DP_BPB
mov CurrFATInMemStartSec,eax
; Calculate how many clusters fit in memory NOTE that since we are
; restricted to 32-bit FAT here we KNOW clusters do not span sector
; boundaries in the FAT.
mov eax,FATSecCntInMem
mov CurrFATInMemSecCnt,eax
movzx ecx,DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
mul ecx
mov ecx,4 ; 4 bytes per cluster
div ecx
mov FATInMemClusCnt,eax
; Init the in memory buffer with the start of the fat
call init_fat_with_header
message msgWriteFat
; Set the rest of the buffer control variables for the in memory buffer
mov CurrentCluster,2
mov CurrFATInMemStartClus,0
ClusLoop2:
call DisplayFatDonePcnt
mov eax,dword ptr DeviceParameters.DP_BPB.BGBPB_RootDirStrtClus
cmp eax,2
jb short NoRootEOF
cmp EAX,TotalClusters
ja short NoRootEOF
sub eax,CurrFATInMemStartClus
jc short NoRootEOF
cmp eax,FATInMemClusCnt
jae short NoRootEOF
shl eax,2 ; * 4 bytes per cluster
mov ecx,00FFFFFFFh
push ds
lds BX,FatSpace ;DS:BX --> FatSpace
assume DS:nothing
ror eax,16 ; AX is high 16 bits of EAX
; which is "64k index" of
; this DWORD
shl ax,12 ; Convert to SEGMENT value
push cx ; Save low 16 of bad mark
mov cx,ds
add cx,ax
mov ds,cx
pop cx
ror eax,16 ; Get back offset in this 64k
add bx,ax ; Index this cluster entry
mov dword ptr ds:[bx],ecx ; Mark as BAD
pop ds
assume DS:data
NoRootEOF:
cmp BadClusBitMap,0 ; Anything to mark?
je short NoBadToMark ; Nope
mov eax,CurrentCluster
push ds
lds si,BadClusBitMap
assume DS:nothing
mov ebx,eax
shr ebx,19 ; (E)BX is "64k index" of this bit
and eax,00007FFFFh ; bit index in that 64k
mov cx,ds
add cx,bx ; Go to correct 64k piece
mov ds,cx
bt dword ptr [si],eax ; Bad cluster?
pop ds
assume DS:data
jnc short NxtClus ; No
mov eax,CurrentCluster
sub eax,CurrFATInMemStartClus
shl eax,2 ; * 4 bytes per cluster
mov ecx,BadClusValue
push ds
lds BX,FatSpace ;DS:BX --> FatSpace
assume DS:nothing
ror eax,16 ; AX is high 16 bits of EAX
; which is "64k index" of
; this DWORD
shl ax,12 ; Convert to SEGMENT value
push cx ; Save low 16 of bad mark
mov cx,ds
add cx,ax
mov ds,cx
pop cx
ror eax,16 ; Get back offset in this 64k
add bx,ax ; Index this cluster entry
mov dword ptr ds:[bx],ecx ; Mark as BAD
pop ds
assume DS:data
NxtClus:
inc CurrentCluster
mov eax,CurrentCluster
sub eax,CurrFATInMemStartClus
cmp eax,FATInMemClusCnt
jae short NextBuf
jmp short TestDone
NoBadToMark:
mov eax,FATInMemClusCnt
cmp CurrentCluster,2 ; Special case?
ja short OkayAdd ; No
sub eax,2 ; Special case for first FAT buffer
OkayAdd:
add CurrentCluster,eax
NextBuf:
call FlushCurrInMemFATBuf
jc short ExitWriteFatCRLFErr
call Fat_Init ; Zero init the in mem buffer
mov eax,CurrFATInMemSecCnt
add eax,CurrFATInMemStartSec
movzx ECX,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors
movzx edx,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
or dx,dx
jnz short GtFatSz2
mov edx,dword ptr DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
GtFatSz2:
add ecx,edx ; First sector after the FAT
cmp eax,ecx ; Start sector in the FAT area?
jae short DoMsgDone ; No, all done, carry clear if jump
mov CurrFATInMemStartSec,eax
sub ecx,eax ; ecx is count of sectors left in FAT
cmp ecx,CurrFATInMemSecCnt ; Partial buffer at end of FAT?
jae short CntOK ; No.
mov CurrFATInMemSecCnt,ecx ; Last part of FAT < buffer size
CntOK:
mov eax,CurrentCluster
mov CurrFATInMemStartClus,eax
TestDone:
mov EAX,CurrentCluster
cmp EAX,TotalClusters ; check for last cluster in FAT
jna ClusLoop2
.8086
call FlushCurrInMemFATBuf ; Sets carry for return
jc ExitWriteFatCRLFErr
DoMsgDone:
message msgSetBadClusDone
clc
jmp short ExitWriteFat
ExitWriteFatCRLFErr:
Message msgCrLf
stc
jmp short ExitWriteFat
WrtWholeFat:
.386
push ds
pop es
assume ES:DATA
movzx cx,DeviceParameters.DP_BPB.oldBPB.BPB_NumberOfFats ;loop control
or CX,CX ;check for zero
jz short ExitWriteFat
movzx eax,ES:DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
or ax,ax
jnz short GotFatSz
mov eax,dword ptr ES:DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
GotFatSz:
movzx EDX,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors ;starting sector
lds BX,FatSpace ;DS:BX --> FatSpace
assume DS:NOTHING,ES:DATA
mov SI,BX ;Set up for add. calc
call SEG_ADJ ;Get adjusted seg:off
mov BX,SI ;Get new offset
WriteFatLoop: ;loop while FATs > 0
;; Manual assemble to prevent compile warning
;; push eax ;Save FAT size
db 066h,050h
;;
push BX ;save Fat offset
push DS ;save Fat segment
push CX ;save Fat count
;; Manual assemble to prevent compile warning
;; push EDX ;Fat start sector
db 066h,052h
;;
mov ecx,eax
mov AL,DriveToFormat
call WriteFatSector ;write the Fat
;; Manual assemble to prevent compile warning
;; pop EDX ;get 1st. Fat sector
db 066h,05Ah
;;
pop CX ;get Fat count
pop DS ;restore Fat segment
pop BX ;restore Fat offset
;; Manual assemble to prevent compile warning
;; pop eax ;restore FAT size
db 066h,058h
;;
jc short ExitWriteFat ;check for errors
add EDX,EAX ;next FAT start sector
loop WriteFatLoop ;write all FATs
ExitWriteFatOK:
clc ;signal success
ExitWriteFat:
pop DS ;restore DS
assume DS:DATA
ret
FlushFATBuf endp
;===========================================================================
; Routine name: GetSetFatEntry
;===========================================================================
;
; Description: Returns or sets the contents of the specified fat
; entry from a specified buffer. The buffer may be
; up to 128K in length for 16 bit FATs and 16K for
; 12 bit FATs.
;
; WARNING: Do not call this if FATNotAllInMem is TRUE
;
; Arguments: DS:SI --> Start of FAT buffer
; EAX = Cluster number
; ECX = 0fffffffeh if get cluster else set cluster from ECX
; ----------------------------------------------------------------
; Returns: EAX --> Contents of FAT entry
; -----------------------------------------------------
; Registers destroyed: EAX EBX ECX EDX
; ----------------------------------------
; Strategy
; --------
;===========================================================================
GetSetFatEntry PROC near
assume DS:NOTHING,ES:DATA
push SI ; Save regs for 'C' compatibility
push DS
push ES
; mov BX,DATA ; ES = DATA
; mov ES,BX
call Seg_Adj ; Normalize the pointer
.386
xor edx,edx
test ES:fBig32Fat,0ffh ; See if 32 bit FAT
jz short TestEntry16 ; If not do 12 bit FAT
shl EAX,1 ; EDX:EAX *= 2
rcl edx,1
jmp short FindEntry16 ; and *2 again for total of *4
TestEntry16:
test ES:fBigFat,0ffh ; See if 16 bit FAT
jz short FindEntry12 ; If not do 12 bit FAT
FindEntry16:
shl EAX,1 ; EDX:EAX *= 2
rcl edx,1
AddToBufStart: ; Offset in EAX may be > 64K
mov EBX,16 ; Convert EDX:EAX to paragraphs
div EBX ; (AX = DX:AX / 16) (DX = DX:AX % 16)
mov BX,DS ; Add paragraphs to DS
add AX,BX
mov DS,AX
add SI,DX ; Add remaining offset in DX to SI
cmp ecx,0fffffffeh ; if ECX == 0fffffffeh, then get entry
jz short GetFatEntry16
test ES:fBig32Fat,0ffh ; See if 32 bit FAT
jz short DoEntry16a
mov dword ptr [SI],ECX ; Set the entry
jmp SHORT GetSetEntryExit
DoEntry16a:
mov word ptr [SI],CX ; Set the entry
jmp SHORT GetSetEntryExitzx ; AX = FAT entry
GetFatEntry16:
test ES:fBig32Fat,0ffh ; See if 32 bit FAT
jz short DoEntry16
mov EAX,dword ptr [SI] ; Move the entry into EAX
and EAX,00FFFFFFFh ; Discard high 4 bits
jmp SHORT GetSetEntryExit ; EAX = FAT entry
.8086
DoEntry16:
mov AX,word ptr [SI] ; Move the entry into AX
jmp SHORT GetSetEntryExitzx ; AX = FAT entry
FindEntry12:
mov BX,AX ; BX = cluster number
shl AX,1
add AX,BX ; AX *= 3
test AX,1 ; Test lsb of AX to see if even or odd
pushf ; Save zero flag
shr AX,1 ; Divid by 2
add SI,AX ; Address the cluster
mov AX,[SI] ; AX = entry + part of another entry
popf ; Get bit test off the stack
jnz OddCluster ; If not zero then it's an odd cluster
EvenCluster:
cmp cx,0fffeh
jz GetEvenCluster ; Check for get or set
and AX,0f000h ; Zero out the value in 12 lsb
or AX,CX ; Set the new value
mov [SI],AX
jmp SHORT GetSetEntryExitzx ; AX = FAT entry
GetEvenCluster:
and AX,0fffh ; Mask off high 4 bits
jmp SHORT GetSetEntryExitzx ; AX = FAT entry
OddCluster:
cmp cx,0fffeh
jz GetOddCluster ; Check for get or set
.386
shl CX,4 ; Set the value Shift left 4 bits
.8086
and AX,0fh ; Zero out existing value in 12 msb
or AX,CX ; Insert new value
mov [SI],AX
jmp SHORT GetSetEntryExitzx ; AX = FAT entry
GetOddCluster:
.386
shr AX,4 ; Shift over 4 bits to get entry
GetSetEntryExitzx:
movzx eax,ax
.8086
GetSetEntryExit:
pop ES ; Restore regs for 'C' compatibility
pop DS
pop SI
ret
GetSetFatEntry ENDP
;===========================================================================
; Routine name: GetFatSectorEntry
;===========================================================================
;
; Description: Returns the contents of the specified fat
; entry from the FatSector buffer. It is assumed that the
; required sector is in the buffer already. If the entry is
; 12 bits and overlaps sectors, the next sector will be read
; into the FatSector buffer.
;
; Arguments: DS:SI --> Start of FatSector buffer
; entry_offset = offset of entry from start of buffer
; fBigFat fBig32Fat = flags for 12-16-32-bit FAT
; -------------------------------------------------------------------------
; Returns: EAX --> Contents of FAT entry
; -----------------------------------------------------
; Registers destroyed: EAX BX CX DX
; ---------------------------------
;
;===========================================================================
GetFatSectorEntry PROC near
assume DS:NOTHING,ES:DATA
push SI ; Save regs for 'C' compatibility
push DS
push ES
; mov BX,DATA ; ES = DATA
; mov ES,BX
call Seg_Adj ; Normalize the pointer
mov DX,ES:entry_offset
add SI,DX ; Add offset value in DX to SI
test ES:fBig32Fat,0ffh ; See if 32 bit FAT
jz short TestEntry16x ; If not do 12-16 bit FAT
.386
mov EAX,dword ptr [SI] ; Move the entry into AX
and EAX,00FFFFFFFh ; Discard high 4 bits
.8086
jmp SHORT GetFatSectorEntryExit ; EAX = FAT entry
TestEntry16x:
test ES:fBigFat,0ffh ; See if 16 bit FAT
jz Get12 ; If not do 12 bit FAT
Get16:
.386
movzx EAX,word ptr [SI] ; Move the entry into AX
.8086
jmp SHORT GetFatSectorEntryExit ; EAX = FAT entry
Get12:
ifdef NEC_98
;;; mov AX,DeviceParameters.DP_BPB.BPB_BytesPerSector
; Fix for B#7418
mov AX,ES:DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
dec AX
cmp DX,AX
else
cmp DX,1ffh ; Entry straddles two FAT sectors if
endif
jb Does_Not_Straddle ; offset is 511 (last byte in sector)
Does_Straddle:
call ReadInTwoParts ; Handle special case by reading in
jmp SHORT GetFatSectorEntryExit ; the next FAT sector also
Does_Not_Straddle:
.386
movzx EAX,word ptr [SI] ; EAX = entry + part of another entry
.8086
test ES:odd_entry,1
jnz IsOddCluster ; If not zero then it's an odd cluster
IsEvenCluster:
and AX,0fffh ; Mask off high 4 bits
jmp SHORT GetFatSectorEntryExit ; EAX = FAT entry
IsOddCluster:
.386
shr AX,4 ; Shift over 4 bits to get entry
.8086
GetFatSectorEntryExit:
pop ES ; Restore regs for 'C' compatibility
pop DS
pop SI
ret
GetFatSectorEntry ENDP
;===========================================================================
;
; ReadInTwoParts : This procedure will determine the value of a 12-bit
; FAT entry which is straddled across two consecutive
; sectors in the FAT. The value is found by reading
; the available part from the first sector, and then
; loading the next sector in the FatSector buffer and
; reading and combining the next part.
; Input : odd_entry
; sector_to_read
; DS:SI pointer to required entry location in buffer (this is
; offset 511 from start of FatSector buffer)
;
; Output: AX = entry value
; FatSector contains next FAT sector
;
; Registers destroyed : AX
;
; Strategy : The position of the entry is different for odd and even
; entries. The 3-byte layout for two consecutive 12-bit entries
; is shown below. (The byte |X1 X0| or |Y2 X2| is the last
; in the buffer).
;
; |X1 X0|Y0 X2|Y2 Y1|
;
; Even entries start at X1 (thus need to get X2X1X0).
; Odd entries start at Y0 (thus need to get Y2Y1Y0).
;
;===========================================================================
ReadInTwoParts proc near
assume DS:NOTHING,ES:DATA
push BX ; Save registers
push CX
push DX
push SI
xor AX,AX
mov AL,BYTE PTR [SI] ; read last byte of buffer
.386
mov EBX,ES:sector_to_read ; compute next sector to read
inc EBX
mov ES:sector_to_read,EBX
.8086
test ES:odd_entry,1
jnz OddEntry
EvenEntry:
push AX
call ReadFatSector ; read in the next FAT sector
pop AX
lds SI,ES:FatSector ; set DS:SI to start of buffer
xor BX,BX
mov BH,BYTE PTR [SI] ; read first byte of buffer
and BH,0fh ; mask out Y2
or AX,BX ; place X2 into position
jmp SHORT EndReadInTwo
OddEntry:
and AL,0f0h ; mask out X2
mov CL,4
shr AX,CL ; place Y0 into position
push AX
call ReadFatSector ; read in the next FAT sector
pop AX
lds SI,ES:FatSector ; set DS:SI to start of buffer
xor BX,BX
mov BL,BYTE PTR [SI] ; read first byte of buffer
mov CL,4
shl BX,CL
or AX,BX ; place Y2 Y1 into position
EndReadInTwo:
pop SI ; Restore registers
pop DX
pop CX
pop BX
ret
ReadInTwoParts endp
AllocInitBadClusBitmap proc near
assume DS:DATA,ES:NOTHING
push es
.386
cmp BadClusBitMap,0
jne short DoneOk
mov ebx, TotalClusters
add ebx,32 ; 32 not 31
shr ebx,5 ; Cnt of DWORDs
shl ebx,2 ; Cnt of BYTEs
add ebx,15
shr ebx,4 ; Cnt of paras
%out BUG limit on bad cluster bitmap
cmp ebx,00005000h ; Bitmap > 320k? (2,621,440 clusters)
ja short ErrExit_Alloc_BCB ; Yes
mov AH, Alloc
int 21h
jc short Exit_Alloc_BCB
mov WORD PTR BadClusBitMap+2,AX
mov es,ax
xor di,di
xor AX,AX
mov WORD PTR BadClusBitMap,AX
movzx ecx,bx ; Cnt of paras
shl ecx,3 ; 8 words per para
mov edx,ecx
NxtBlock:
cmp ecx,8000h ; More than 64k left?
jbe short ZotIt ; Nope, last one
mov ecx,00008000h ; Do at most 64k at a time
ZotIt:
mov ebx,ecx ; Save count
cld
rep stosw ; zero init bit array
sub edx,ebx ; Sub off amount done
jbe short DoneOk ; All done
mov ax,es
add ax,1000h ; Next 64k
mov es,ax
xor di,di
mov ecx,edx
jmp short NxtBlock
.8086
DoneOk:
clc
Exit_Alloc_BCB:
pop es
ret
ErrExit_Alloc_BCB:
stc
jmp short Exit_Alloc_BCB
AllocInitBadClusBitmap endp
;*** SetUpBadClusTransfer - Set things up to copy bad clusters from the current
; disk to the new disk.
;
; DS -> data
;
SetUpBadClusTransfer proc near
assume DS:DATA,ES:NOTHING
mov word ptr BadClusBitMap,0
mov word ptr BadClusBitMap+2,0
cmp FATNotAllInMem,0
.386
je InitFatWithBad
call DetermineExistingFormatNoMsg
cmc
jnc AllDone6 ; Drive isn't valid so no bad sectors
;
; Build a bit map of the bad clusters
;
message msgSetBadClus
.386
test fBig32FAT,0ffh ; See if 32 bit fat
jz short Tst16BitEntry ; If zero then 16 or 12 bit fat
mov EBX,00ffffff7h ; Set 32 bit value for bad cluster
jmp SHORT SetBdVal
Tst16BitEntry:
mov EBX,00000ff7h ; Set 12 bit value for bad cluster
test fBigFAT,0ffh ; See if 16 bit fat
jz short SetBdVal ; If zero then 12 bit fat
mov EBX,0000fff7h ; Set 16 bit value for bad cluster
SetBdVal:
mov CurrentCluster,2
mov BadClusValue,EBX
push ds
pop es ; following routines expect ES->DATA
ClusLoop:
call DisplayFatDonePcnt
mov EAX,CurrentCluster
call calc_sector_and_offset ; determine location of this entry
mov EBX,sector_in_buffer
mov EAX,sector_to_read
cmp EAX,EBX ; check if required sector is in buffer
je short DontHaveToRead2
call ReadFatSector ; read a sector of the FAT into buffer
jc short AllDoneDoCRLFErr
DontHaveToRead2:
mov EAX,CurrentCluster ; EAX = current cluster
xor CX,CX ; ECX = get cluster contents signal
push ds
lds SI,FatSector ; DS:SI --> FAT buffer
call GetFatSectorEntry ; EAX = contents of FAT entry
pop ds
cmp EAX,BadClusValue ; Is this cluster marked bad?
jne short NextClus ; If EAX<>EBX good cluster
call AllocInitBadClusBitmap ; Does nothing if BadClusBitMap
jc short AllDoneDoCRLFErr ; already exists
mov EAX,CurrentCluster ; EAX = this cluster number
push ds
lds si,BadClusBitMap
mov ebx,eax
shr ebx,19 ; (E)BX is "64k index" of this bit
and eax,00007FFFFh ; bit index in that 64k
mov cx,ds
add cx,bx ; Go to correct 64k piece
mov ds,cx
bts dword ptr [si],eax ; Set the bit
pop ds
NextClus:
inc CurrentCluster ; go to next cluster
mov EAX,CurrentCluster
mov EBX,TotalClusters
cmp EAX,EBX ; check for last cluster in FAT
.8086
jna ClusLoop
message msgSetBadClusDone
jmp short AllDone6Ok
AllDoneDoCRLFErr:
message msgCRLF
stc
jmp short AllDone6
InitFatWithBad:
call load_old_fat ; load old FAT
call mark_non_bad_as_free ; mark anything not BAD as FREE
AllDone6Ok:
clc
AllDone6:
ret
SetUpBadClusTransfer endp
;*** mark_non_bad_as_free -- mark all non-bad blocks as free in the FAT
;
; WARNING: Do not call this if FATNotAllInMem is TRUE
;
mark_non_bad_as_free proc near
assume ds:nothing, es:DATA
.386
test fBig32FAT,0ffh ; See if 32 bit fat
mov ebx,00ffffff7h ; get bad value for 32-bit
jnz short mark_non_bad_1
test fBigFAT,0ffh ; See if 16 bit fat
mov ebx,0fff7h ; get bad value for 16-bit
jnz short mark_non_bad_1
and bh,0fh ; get the 0ff7h for 12-bit
mark_non_bad_1:
mov eax,2 ; cluster number
mark_non_bad_2:
push ds
lds si,FatSpace ; point to the FAT buffer
mov ecx,0fffffffeh ; get the FAT entry
;; Manual to disable compile warning
;; push eax ; save cluster number
db 066h,050h
;; push ebx ; save bad value
db 066h,053h
call GetSetFatEntry ; read the cluster value
;; pop ebx
db 066h,05Bh
cmp eax,ebx ; is it bad?
jz short mark_non_bad_3 ; skip if so (leave alone)
;; pop eax ; get the cluster number
db 066h,058h
;; push eax
db 066h,050h
;; push ebx
db 066h,053h
xor ecx,ecx ; set FAT entry to FREE
call GetSetFatEntry
;; pop ebx
db 066h,05Bh
mark_non_bad_3:
;; pop eax ; restore cluster number
db 066h,058h
pop ds
inc eax
cmp eax,TotalClusters
jna mark_non_bad_2
.8086
ret
mark_non_bad_as_free endp
;*** load_old_fat -- loads the FAT from the existing media into FatSpace
;
; WARNING: Do not call this if FATNotAllInMem is TRUE
;
; If not properly formatted, will just terminate.
; If any error reading FAT, will zero entire FAT via Fat_Init.
load_old_fat proc near
mov SI,DATA
mov ES,SI ; Set ES to data segment
assume ES:DATA,DS:Nothing ; Assembler directive
push ds
call DetermineExistingFormatNoMsg
jc load_old_fat_error
call init_fat_with_header
mov CX, DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
.errnz EDP_BPB NE DP_BPB
or cx, cx
jnz short GotFSz
;
; We KNOW the high word must be 0 since whole FAT fits in memory
;
mov cx, DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
GotFSz:
mov DX,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors ;starting sector
mov AL,DriveToFormat
lds bx,FatSpace
load_old_fat_1:
jcxz load_old_fat_done ; exit when done
ifdef NEC_98
push cx ; save size to write
cmp cx,10h ; need more than 40h secs?
jb load_old_fat_2 ; skip if we can get it all
mov cx,10h ; clip to max
load_old_fat_2:
push AX ; save AX
call Read_Disk ; read it
pop AX ; restore AX
pop CX ; restore CX
jc load_old_fat_error ; exit if error
push ax
mov ax,ds
add ax,es:DeviceParameters.DP_BPB.BPB_BytesPerSector; adjust segment
mov ds,ax
pop ax
add DX,10h
sub CX,10h
ja load_old_fat_1 ; loop until done
else
push cx ; save size to write
cmp cx,40h ; need more than 40h secs?
jb load_old_fat_2 ; skip if we can get it all
mov cx,40h ; clip to max
load_old_fat_2:
push AX ; save AX
call Read_Disk ; read it
pop AX ; restore AX
pop CX ; restore CX
jc load_old_fat_error ; exit if error
push ax
mov ax,ds
add ax,40h*512/16 ; adjust segment
mov ds,ax
pop ax
add DX,40h
sub CX,40h
ja load_old_fat_1 ; loop until done
endif
load_old_fat_done:
pop ds
jmp short init_fat_header
load_old_fat_error:
pop ds
if2
.errnz (offset $) - (offset init_fat_with_header) ; fall thru!
endif
load_old_fat endp
;*** init_fat_with_header -- Do a Fat_Init, and then put bytes at front
;
; alternate entry point: init_fat_header (just fill in header)
init_fat_with_header proc near
assume ds:nothing, es:DATA
mov DI,DATA
mov ES,DI
call Fat_Init
init_fat_header:
push ES
push es
pop ds ; get ds -> DATA
assume ds:DATA
les DI, FatSpace ; ES:DI --> FatSpace buffer
assume es:nothing ; Store media descriptor byte
mov AL, DeviceParameters.DP_BPB.oldBPB.BPB_MediaDescriptor
.errnz EDP_BPB NE DP_BPB
ifdef NEC_98
cmp AL,Fixed_Disk ;FAT-ID twisted (for HD and 5"MO)
jne @F ; F8h --> FEh (Only FAT-ID)
mov AL,Single_8_Media ;it is NEC_98 local.
@@:
endif
mov AH, 0ffH
stosw ; Cluster 0 start
mov al,ah
stosb ; cluster 0 if 32 bit else cluster 1
test fBig32Fat, TRUE
jz Not32
stosb ; finish cluster 0 dword
stosw ; cluster 1 dword
and ah,0Fh ; High nibble reserved, zero it.
stosw
sub di,5 ; Go back to high byte of cluster 0
mov al,ah
stosb ; High nibble reserved, zero it.
jmp short NotBig
Not32:
test fBigFat, TRUE
jz NotBig
stosb ; finish cluster 1 word
NotBig:
pop ES
ret
init_fat_with_header endp
;**** IsThisClusterBad
;
; ENTRY: EAX is cluster #
;
; EXIT: Zero set if cluster bad
;
; USES: EBX,ECX,EDX,FLAGS
;
IsThisClusterBad proc near
assume ds:data, es:data
push ds
push si
.386
;; push eax
db 066h,050h
cmp FATNotAllInMem,0
je short ChkInMemFat
cmp BadClusBitMap,0 ; Anything marked?
je short NotBadRet ; Nope
lds si,BadClusBitMap
assume DS:nothing
mov ebx,eax
shr ebx,19 ; (E)BX is "64k index" of this bit
and eax,00007FFFFh ; bit index in that 64k
mov cx,ds
add cx,bx ; Go to correct 64k piece
mov ds,cx
bt dword ptr [si],eax ; Bad cluster?
jnc short NotBadRet ; No
mov bx,0FFFFh ; Set so following inc sets ZERO
NotBadRet:
inc bx
PopRet:
;; pop eax ; restore cluster number
db 066h,058h
.8086
pop si
pop ds
ret
ChkInMemFat:
.386
assume DS:data
test fBig32FAT,0ffh
jz short Tst16BitEnt
mov EBX,00ffffff7h
jmp SHORT SetBVal
Tst16BitEnt:
mov EBX,00000ff7h
test fBigFAT,0ffh
jz short SetBVal
mov EBX,0000fff7h
SetBVal:
mov BadClusValue,EBX
mov ECX,0fffffffeh ; ECX = Get value
lds SI,FatSpace
assume DS:nothing
call GetSetFatEntry
cmp eax,es:BadClusValue
.8086
jmp short PopRet
IsThisClusterBad endp
;**** WrtEOFMrkInRootClus
;
; ENTRY: None
;
; EXIT: EOF mark written into root directory staring cluster
;
; USES: EAX,EBX,ECX,EDX,FLAGS
;
WrtEOFMrkInRootClus proc near
assume ds:data, es:data
push ds
push si
;
; In FATNotAllInMem case FlushFatBuf will take care of putting
; an eof mark in the root clus
;
cmp FATNotAllInMem,0
jne SetDone
test fBig32FAT,0ffh ; See if 32 bit fat
jz SetDone ; No
.386
mov eax,dword ptr DeviceParameters.DP_BPB.BGBPB_RootDirStrtClus
.errnz EDP_BPB NE DP_BPB
cmp eax,2
jb short SetDone
cmp eax,TotalClusters
ja short SetDone
mov ECX,00fffffffh
.8086
lds SI,FatSpace
assume DS:nothing
call GetSetFatEntry
SetDone:
pop si
pop ds
ret
WrtEOFMrkInRootClus endp
CODE ENDS
END