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.
2029 lines
53 KiB
2029 lines
53 KiB
;/*
|
|
; * Microsoft Confidential
|
|
; * Copyright (C) Microsoft Corporation 1991
|
|
; * All Rights Reserved.
|
|
; */
|
|
;===========================================================================
|
|
;
|
|
; FILE: PHASE1.ASM
|
|
;
|
|
;===========================================================================
|
|
|
|
;===========================================================================
|
|
;Include file declarations
|
|
;===========================================================================
|
|
debug equ 0
|
|
.xlist
|
|
INCLUDE DOSEQUS.INC
|
|
INCLUDE DOSMAC.INC
|
|
INCLUDE SYSCALL.INC
|
|
INCLUDE ERROR.INC
|
|
INCLUDE DIRENT.INC
|
|
INCLUDE BPB.INC
|
|
INCLUDE BOOTSEC.INC
|
|
INCLUDE FOREQU.INC
|
|
INCLUDE FORMACRO.INC
|
|
INCLUDE IOCTL.INC
|
|
INCLUDE FORSWTCH.INC
|
|
.list
|
|
;
|
|
;---------------------------------------------------------------------------
|
|
;
|
|
; M020 : Looked for EXT_BOOT_SIG before assuming that the BPB in the boot
|
|
; sector is an extended one. Bug #4946
|
|
;
|
|
;---------------------------------------------------------------------------
|
|
;
|
|
|
|
|
|
|
|
;===========================================================================
|
|
; Data segment
|
|
;===========================================================================
|
|
|
|
DATA SEGMENT PUBLIC PARA 'DATA'
|
|
|
|
;===========================================================================
|
|
; Declarations for all publics in other modules used by this module
|
|
;===========================================================================
|
|
|
|
;Constants
|
|
EXTRN EXIT_NO :ABS
|
|
EXTRN EXIT_FATAL :ABS
|
|
;Bytes
|
|
EXTRN CMCDDFlag :BYTE
|
|
|
|
EXTRN ValidSavedDeviceParameters:BYTE
|
|
EXTRN DriveToFormat :BYTE
|
|
EXTRN msgFormatNotSupported :BYTE
|
|
EXTRN msgInsertDisk :BYTE
|
|
EXTRN msgInvalidDeviceParameters:BYTE
|
|
EXTRN ContinueMsg :BYTE
|
|
EXTRN msgNotCompatablePart :BYTE
|
|
EXTRN msgExistingFormatDiffers :BYTE
|
|
EXTRN msgNoQuickFormat :BYTE
|
|
EXTRN msgCrLf :BYTE
|
|
EXTRN msgCheckExistingDiskFormat:BYTE
|
|
EXTRN Extended_Error_Msg :BYTE
|
|
EXTRN old_dir :BYTE
|
|
EXTRN ExitStatus :BYTE
|
|
ifdef NEC_98
|
|
EXTRN SizeMap :BYTE
|
|
EXTRN msgInsufficientMemory :BYTE
|
|
endif
|
|
|
|
;Words
|
|
EXTRN SectorsInRootDirectory :WORD
|
|
EXTRN Paras_Per_Fat :WORD
|
|
EXTRN SwitchMap :WORD
|
|
EXTRN SwitchMap2 :WORD
|
|
EXTRN SwitchCopy :WORD
|
|
ifdef NEC_98
|
|
EXTRN SASI1024Table :WORD
|
|
EXTRN SCSI1024Table :WORD
|
|
EXTRN Small2048Table :WORD
|
|
EXTRN Large512Table :WORD
|
|
EXTRN Large256Table :WORD
|
|
else
|
|
EXTRN DiskTable :WORD
|
|
EXTRN DiskTable2 :WORD
|
|
endif
|
|
EXTRN RWErrorCode :WORD
|
|
|
|
;Pointers
|
|
EXTRN FatSpace :DWORD
|
|
|
|
;Structures
|
|
EXTRN SavedParams :BYTE
|
|
EXTRN DeviceParameters :BYTE
|
|
EXTRN IsExtRAWIODrv :BYTE
|
|
EXTRN SwitchDevParams :BYTE
|
|
EXTRN Read_Write_Relative :BYTE
|
|
EXTRN SetDPBPacket :BYTE
|
|
|
|
fBigFat DB FALSE
|
|
fBig32Fat DB FALSE
|
|
ThisSysInd DB 0 ; indicates size of FAT
|
|
|
|
StartSector DD ? ; holds first data sector
|
|
TotalClusters DD ? ; holds total #clusters on disk
|
|
|
|
UnformattedHardDrive DB ?
|
|
ifdef NEC_98
|
|
SAV_INT24_OFF DW 0 ; original int 24 vector address
|
|
SAV_INT24_SEG DW 0
|
|
endif
|
|
|
|
MediaSensePacket A_MEDIA_SENSE <> ; structure used in media
|
|
; sensing call
|
|
|
|
; the following table provides templates for
|
|
; BPBs used in CP/M disks.
|
|
; Order is very important (used by both MSFOR and PHASE1)
|
|
|
|
CustomCPMBPBs LABEL BYTE
|
|
BPB320 a_BPB <512, 2, 1, 2, 112, 2*8*40, 0ffh, 1, 8, 2, 0, 0, 0, 0>
|
|
BPB160 a_BPB <512, 1, 1, 2, 64, 1*8*40, 0feh, 1, 8, 1, 0, 0, 0, 0>
|
|
BPB360 a_BPB <512, 2, 1, 2, 112, 2*9*40, 0fdh, 2, 9, 2, 0, 0, 0, 0>
|
|
BPB180 a_BPB <512, 1, 1, 2, 64, 1*9*40, 0fch, 2, 9, 1, 0, 0, 0, 0>
|
|
|
|
EndCustomCPMBPBs LABEL BYTE
|
|
|
|
; This must folow CustomCPMBPBs
|
|
|
|
BPB12 a_BPB <512, 1, 1, 2, 224, 2*15*80, 0F9h, 7, 15, 2, 0, 0, 0, 0>
|
|
BPB720 a_BPB <512, 2, 1, 2, 112, 2* 9*80, 0F9h, 3, 9, 2, 0, 0, 0, 0>
|
|
BPB1440 a_BPB <512, 1, 1, 2, 224, 2*18*80, 0F0h, 9, 18, 2, 0, 0, 0, 0>
|
|
BPB2880 a_BPB <512, 2, 1, 2, 240, 2*36*80, 0F0h, 9, 36, 2, 0, 0, 0, 0>
|
|
ifdef NEC_98
|
|
BPB640 a_BPB <512, 2, 1, 2, 112, 2* 8*80, 0FBh, 2, 8, 2, 0, 0, 0, 0>
|
|
BPB1250 a_BPB <1024,1, 1, 2, 192, 2* 8*77, 0FEh, 2, 8, 2, 0, 0, 0, 0>
|
|
BPB128 a_BPB <512,4,1, 2, 512, 0, 0F0h, 0F3h, 019h, 1, 0,0, 0CBE0h, 03h>
|
|
BPB230 a_BPB <512,8,1, 2, 512, 0, 0F0h, 0DAh, 019h, 1, 0,0, 0CF75h, 06h>
|
|
BPB650 a_BPB <512,020h,1, 2, 512, 0, 0F0h, 09Fh, 019h, 1, 0,0, 0D040h, 013h>
|
|
endif
|
|
EndStandardBPBs LABEL BYTE
|
|
|
|
; the following table indicates the switches
|
|
; which must be set for the given CP/M media
|
|
CPMSwitchTable LABEL BYTE
|
|
dw Switch_4 + Switch_8 ;320K
|
|
dw Switch_1 + Switch_4 + Switch_8 ;160K
|
|
dw Switch_4 ;360K
|
|
dw Switch_1 + Switch_4 ;180K
|
|
|
|
; ========================================================================
|
|
; Tables added for media sense support in 5.00.
|
|
; ========================================================================
|
|
|
|
MediaTable LABEL WORD
|
|
|
|
ifdef NEC_98
|
|
dw 0 ; 0
|
|
dw OFFSET BPB12 ; 1 /5
|
|
dw OFFSET BPB720 ; 2 /9
|
|
dw 0 ; 3
|
|
dw OFFSET BPB1250 ; 4 /M
|
|
dw 0 ; 5
|
|
dw 0 ; 6
|
|
dw OFFSET BPB1440 ; 7 /4
|
|
dw 0 ; 8
|
|
dw OFFSET BPB2880 ; 9 not supported! but rest.
|
|
else
|
|
dw 0 ; 0
|
|
dw 0 ; 1
|
|
dw OFFSET BPB720 ; 2
|
|
dw 0 ; 3
|
|
dw 0 ; 4
|
|
dw 0 ; 5
|
|
dw 0 ; 6
|
|
dw OFFSET BPB1440 ; 7
|
|
dw 0 ; 8
|
|
dw OFFSET BPB2880 ; 9
|
|
endif
|
|
|
|
EndMediaTable LABEL WORD
|
|
|
|
DATA ENDS
|
|
|
|
;===========================================================================
|
|
; Executable code segment
|
|
;===========================================================================
|
|
|
|
CODE SEGMENT PUBLIC PARA 'CODE'
|
|
ASSUME CS:CODE, DS:DATA, ES:DATA
|
|
|
|
|
|
;===========================================================================
|
|
; Declarations for all externs
|
|
;===========================================================================
|
|
|
|
;Functions
|
|
EXTRN AccessDisk :NEAR
|
|
EXTRN USER_STRING :NEAR
|
|
EXTRN CrLf :NEAR
|
|
EXTRN CheckSwitches :NEAR
|
|
EXTRN Read_Disk :NEAR
|
|
EXTRN Yes? :NEAR
|
|
ifdef NEC_98
|
|
EXTRN GetDeviceParameters :NEAR
|
|
EXTRN Alloc_Dir_Buf :NEAR
|
|
EXTRN Alloc_Fat_Buf :NEAR
|
|
EXTRN Alloc_Fat_Sec_Buf :NEAR
|
|
EXTRN Alloc_DirBuf2 :NEAR
|
|
EXTRN Alloc_Cluster_Buf :NEAR
|
|
ifdef OPKBLD
|
|
EXTRN Do_Switch_S :NEAR
|
|
endif ;OPKBLD
|
|
EXTRN ZeroAllBuffers :NEAR
|
|
endif ;NEC_98
|
|
|
|
;Labels
|
|
EXTRN FatalExit :NEAR
|
|
EXTRN ExitProgram :NEAR
|
|
|
|
|
|
;===========================================================================
|
|
; Declarations for all publics in this module
|
|
;===========================================================================
|
|
|
|
PUBLIC Phase1Initialisation
|
|
PUBLIC MediaSense
|
|
PUBLIC TargPrm
|
|
PUBLIC CopyToSwitchDevParams
|
|
PUBLIC CompareDevParams
|
|
PUBLIC LoadSwitchDevParams
|
|
PUBLIC DetermineExistingFormat
|
|
PUBLIC DetermineExistingFormatNomsg
|
|
PUBLIC IsValidBpb
|
|
PUBLIC ResetDeviceParameters
|
|
PUBLIC DetermineCPMFormat
|
|
PUBLIC SetCPMParameters
|
|
PUBLIC Set_BPB_Info
|
|
PUBLIC Scan_Disk_Table
|
|
PUBLIC Calc_Big16_Fat
|
|
PUBLIC Calc_Big32_Fat
|
|
PUBLIC Calc_Small_Fat
|
|
PUBLIC SetStartSector
|
|
PUBLIC SetfBigFat
|
|
PUBLIC GetTotalClusters
|
|
PUBLIC fBigFat
|
|
PUBLIC fBig32Fat
|
|
PUBLIC StartSector
|
|
PUBLIC TotalClusters
|
|
PUBLIC CustomCPMBPBs
|
|
PUBLIC CPMSwitchTable
|
|
PUBLIC EndStandardBPBs
|
|
PUBLIC BPB720
|
|
ifdef NEC_98
|
|
PUBLIC BPB640
|
|
PUBLIC BPB12
|
|
PUBLIC BPB1250
|
|
PUBLIC BPB128
|
|
PUBLIC BPB230
|
|
PUBLIC BPB650
|
|
endif
|
|
PUBLIC UnformattedHardDrive
|
|
|
|
; ==========================================================================
|
|
; Phase1Initialisation:
|
|
; This routine sets up fBigFat
|
|
; It also does most of the other initialisation
|
|
;
|
|
; Algorithm:
|
|
; Perform media sensing and if present adjust DeviceParameters
|
|
; Check switches against parameters
|
|
; Use switches to modify device parameters
|
|
; Save a copy of current DeviceParameters in SwitchDevParams
|
|
;
|
|
; IF (!SWITCH_U)
|
|
; {
|
|
; IF (!ValidBootRecord || !ValidBPB)
|
|
; set SWITCH_U
|
|
; ELSE
|
|
; {
|
|
; get device layout from BPB on disk
|
|
; IF (DeviceParameters = SwitchDevParams)
|
|
; do safe/quick format
|
|
; ELSE
|
|
; {
|
|
; IF (Switch_N || Switch_T || Switch_F)
|
|
; {
|
|
; Issue warning
|
|
; Format with BPB from SwitchDevParams if user continues
|
|
; }
|
|
; ELSE
|
|
; do safe/quick format
|
|
; }
|
|
; }
|
|
; }
|
|
;
|
|
; Calculate start sector (first sector not used by DOS)
|
|
; fBig32Fat = (((TotalSectors - StartSector)/SectorsPerCluster) >= 65526)
|
|
; fBigFat = (((TotalSectors - StartSector)/SectorsPerCluster) >= 4086)
|
|
; ==========================================================================
|
|
|
|
Phase1Initialisation proc near
|
|
|
|
; use DevParms to check for removable
|
|
test DeviceParameters.DP_DeviceAttributes,1
|
|
.errnz EDP_DEVICEATTRIBUTES NE DP_DEVICEATTRIBUTES
|
|
jnz @F ; Bit 0=1 --> not removable
|
|
|
|
; New media sensing call added for 5.00 will see if
|
|
; see if media sensing is avaliable and if it is will
|
|
; reset DeviceParameters to the real parameters for
|
|
; the type of disk being formatted.
|
|
|
|
ifndef NEC_98
|
|
call MediaSense
|
|
else
|
|
cmp DeviceParameters.DP_DeviceType, DEV_HARDDISK ; Hard disk?
|
|
.errnz EDP_DEVICETYPE NE DP_DEVICETYPE
|
|
jne @F ; No
|
|
|
|
; We ignore INT24 in order not to be stop formatting
|
|
; when "INT21 AH=32" is called.
|
|
|
|
; Set my INT24
|
|
push es
|
|
mov ah, 35h
|
|
mov al, 24h
|
|
int 21h ; get INT24's vector address
|
|
mov SAV_INT24_OFF, bx ; save original INT24
|
|
mov SAV_INT24_SEG, es ; save original INT24
|
|
pop es
|
|
|
|
push ds
|
|
push cs
|
|
pop ds
|
|
mov ah, 25h
|
|
mov al, 24h
|
|
mov dx, OFFSET MY_INT24
|
|
int 21h ; set my INT24
|
|
pop ds
|
|
|
|
; Update Default BPB
|
|
push ds
|
|
push bx
|
|
mov ah, 32h
|
|
mov dl, DriveToFormat
|
|
inc dl
|
|
int 21h ; Get Drive Parameter Block
|
|
pop bx
|
|
pop ds
|
|
|
|
; Set original INT 24
|
|
push ds
|
|
push dx
|
|
mov ah, 25h
|
|
mov al, 24h
|
|
mov ds, SAV_INT24_SEG
|
|
mov dx, SAV_INT24_OFF
|
|
int 21h ; set original INT24
|
|
pop dx
|
|
pop ds
|
|
|
|
; Get default BPB
|
|
lea DX, DeviceParameters
|
|
mov DeviceParameters.DP_SpecialFunctions, 0
|
|
call GetDeviceParameters
|
|
|
|
; Allocate memory
|
|
call Alloc_Dir_Buf ; Allocate root directory buffer
|
|
jc gi_memerr
|
|
|
|
call Alloc_Fat_Buf ; Allocate FAT buffer
|
|
jc gi_memerr
|
|
|
|
call Alloc_Fat_Sec_Buf ; Allocate fat sector buffer
|
|
jc gi_memerr
|
|
|
|
call Alloc_DirBuf2 ; Allocate 1-sector buffer DirBuf (general-
|
|
; purpose use)
|
|
jc gi_memerr
|
|
|
|
call Alloc_Cluster_Buf ; get room for retry buffer
|
|
|
|
ifdef OPKBLD
|
|
call Do_Switch_S ; Load system files if needed
|
|
; carry flag determined by Do_Switch_S
|
|
else
|
|
clc
|
|
endif ;OPKBLD
|
|
call ZeroAllBuffers ; initialize buffers
|
|
jmp short @f
|
|
|
|
gi_memerr:
|
|
Message msgInsufficientMemory
|
|
stc
|
|
ret
|
|
endif
|
|
@@:
|
|
; Ensure that there is a valid #
|
|
; of Sectors in the track table
|
|
|
|
mov ValidSavedDeviceParameters, 1
|
|
cmp IsExtRAWIODrv,0
|
|
je OldTabOff2
|
|
|
|
mov SavedParams.EDP_TrackTableEntries, 0
|
|
mov DeviceParameters.EDP_TrackTableEntries,0
|
|
jmp short SetBPBnf
|
|
|
|
OldTabOff2:
|
|
mov SavedParams.DP_TrackTableEntries, 0
|
|
; Initialise to zero to see if
|
|
; CheckSwitches define track layout
|
|
mov DeviceParameters.DP_TrackTableEntries,0
|
|
SetBPBnf:
|
|
call Set_BPB_Info ; 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
|
|
|
|
call CopyToSwitchDevParams ; Save a copy of deviceparameters as
|
|
; returned by CheckSwitches
|
|
|
|
mov ax,SwitchMap ; No need to check existing format
|
|
and ax,SWITCH_U+SWITCH_Q
|
|
cmp ax,SWITCH_U ; if unconditional format specified
|
|
jnz CheckExistingFormat
|
|
jmp DevParamsOk
|
|
|
|
CheckExistingFormat:
|
|
|
|
; New call added for 5.00 to see if the disk has been
|
|
; previously formatted, and if so this will reset
|
|
; DeviceParameters to those of the existing format.
|
|
|
|
call DetermineExistingFormat
|
|
jnc ValidExistingFormat ; carry clear if valid existing format
|
|
|
|
InvalidExistingFormat:
|
|
and RWErrorCode,0ffh ; check low byte for 'drive not ready' error
|
|
cmp RWErrorCode,ERROR_I24_NOT_READY ;'not ready' error code = 2
|
|
jne CheckForQ ; no error reading disk
|
|
|
|
; 'not ready' error occurred, give msg
|
|
mov AX,21 ; load AX with extended error code for not ready
|
|
SetFatalErr:
|
|
Extended_Message ; deliver message "Not Ready"
|
|
mov ExitStatus,EXIT_FATAL ; M006;
|
|
stc
|
|
jmp EndPhase1
|
|
|
|
CheckForQ:
|
|
test SwitchMap,SWITCH_Q ; Need to give message if /q was specified
|
|
jz MakeUnconditional
|
|
|
|
test SwitchCopy,(SWITCH_T or SWITCH_N or SWITCH_F) ; did user specify size?
|
|
jnz TurnOffQ ; do an unconditional format at specified size
|
|
ifdef OPKBLD
|
|
; Let OEM's quickformat a clean disk
|
|
test DeviceParameters.DP_DeviceAttributes,1
|
|
jnz DevParamsOk ; Bit 0=1 --> not removable
|
|
endif ;OPKBLD
|
|
Message msgNoQuickFormat ; Inform user quick format cannot be done
|
|
call Yes? ; Continue with unconditional format?
|
|
|
|
pushf
|
|
Message msgCrLf
|
|
popf
|
|
|
|
jnc TurnOffQ
|
|
mov ExitStatus,EXIT_NO ; load exit code 5 (response is 'no')
|
|
jmp ExitProgram ; User wants to exit
|
|
|
|
TurnOffQ:
|
|
and SwitchMap,NOT SWITCH_Q ; Turn off /Q to continue
|
|
|
|
MakeUnconditional:
|
|
or SwitchMap,SWITCH_U ; Enable /U since invalid existing format
|
|
or SwitchMap2, Switch2_C ; Enable /C since invalid existing format
|
|
jmp SHORT DevParamsOk ; Device parameters will not have been
|
|
; modified since invalid existing format
|
|
|
|
ValidExistingFormat:
|
|
call CompareDevParams ; see if SwitchDevParams = DeviceParameters
|
|
jnc DevParamsOk ; they are equal
|
|
|
|
; Check if user had specified a format
|
|
; size, since DeviceParameters on disk
|
|
; are different.
|
|
|
|
test SwitchMap,SWITCH_Q ; special case where size was specified
|
|
; together with /Q :- use size specified
|
|
; only if invalid existing format
|
|
jnz DevParamsOk ; use the parameters found on disk
|
|
or SwitchMap,SWITCH_U ; Enable /U since new format specified
|
|
or SwitchMap2, Switch2_C ; Enable /C since new format specified
|
|
call LoadSwitchDevParams ; Set deviceparameters to SwitchDevParams
|
|
; i.e. follow user-specified size
|
|
DevParamsOk:
|
|
call SetDOS_Dpb ; m035 Setup default DOS DPB for this
|
|
; drive (for memory cards).
|
|
jc SetFatalErr
|
|
; Store sector table info (layout of
|
|
; each track)
|
|
mov CX, DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack;CX = loop count
|
|
.errnz EDP_BPB NE DP_BPB
|
|
mov AX, 1 ;AX = sector #
|
|
mov BX, DeviceParameters.DP_BPB.oldBPB.BPB_bytesPerSector ;BX = sector size
|
|
cmp IsExtRAWIODrv,0
|
|
je OldTabOff
|
|
|
|
cmp DeviceParameters.EDP_TrackTableEntries,0
|
|
jne TrackLayoutSet ; There is a good track layout
|
|
mov DeviceParameters.EDP_TrackTableEntries,CX
|
|
lea DI, DeviceParameters.EDP_SectorTable
|
|
jmp short GotTabOff
|
|
|
|
OldTabOff:
|
|
cmp DeviceParameters.DP_TrackTableEntries,0
|
|
jne TrackLayoutSet ; There is a good track layout
|
|
mov DeviceParameters.DP_TrackTableEntries,CX
|
|
lea DI, DeviceParameters.DP_SectorTable
|
|
GotTabOff:
|
|
cld
|
|
LoadSectorTable:
|
|
stosw ; Write the sector number
|
|
xchg AX, BX ; Get the sector size in bytes
|
|
stosw ; Write the sector size
|
|
xchg AX, BX
|
|
inc AX ; Go to the next sector
|
|
loop LoadSectorTable
|
|
|
|
TrackLayoutSet:
|
|
call SetStartSector
|
|
call SetfBigFat
|
|
call GetTotalClusters
|
|
clc
|
|
|
|
EndPhase1:
|
|
return
|
|
|
|
Phase1Initialisation endp
|
|
|
|
; =========================================================================
|
|
;
|
|
; MediaSense
|
|
; Checks for media sensing via IOCtl 440d subfuction 0868.
|
|
; If sensing is supported the user will be prompted to insert
|
|
; the disk if it's not detect and then the device parameters
|
|
; will be set according to the type of media being used.
|
|
;
|
|
; Before we can use the type returned we must be sure it's
|
|
; not a larger size disk than is formattable in the drive.
|
|
; We can do this by checking the media type byte in the
|
|
; saved device parameters.
|
|
;
|
|
; Input:
|
|
; DriveToFormat - Must have already been set
|
|
;
|
|
; =========================================================================
|
|
|
|
MediaSense PROC NEAR
|
|
|
|
mov BL, DriveToFormat
|
|
inc BX
|
|
|
|
mov CX, (RAWIO shl 8) or SENSE_MEDIA_TYPE
|
|
cmp IsExtRAWIODrv,0
|
|
je DoIOCTL1
|
|
mov CX, (EXTRAWIO shl 8) or SENSE_MEDIA_TYPE
|
|
DoIOCTL1:
|
|
lea DX,MediaSensePacket
|
|
|
|
; First check if BIOS supports call
|
|
mov AX, (IOCTL shl 8) or IOCTL_QUERY_BLOCK
|
|
int 21h
|
|
jc MediaSenseExit
|
|
|
|
; Now do actual call
|
|
mov AX, (IOCTL shl 8) or GENERIC_IOCTL
|
|
int 21h
|
|
|
|
jnc GotMediaSense
|
|
|
|
cmp AL,error_not_ready
|
|
jne MediaSenseExit ; Machine does not support media sensing
|
|
|
|
call TargPrm ; Insert disk prompt
|
|
jmp SHORT MediaSense ; Retry the operation
|
|
|
|
; See if the type of media inserted is the same as the
|
|
; default for this type of drive and if not check to
|
|
; be sure it's
|
|
|
|
GotMediaSense:
|
|
mov AL,MediaSensePacket.MS_DEVICETYPE ; AL == media type
|
|
cmp SavedParams.DP_DEVICETYPE,AL ; If the media in the
|
|
.errnz EDP_DEVICETYPE NE DP_DEVICETYPE
|
|
jl MediaSenseExit ; drv is > default size, use default
|
|
|
|
; Load BPB for sensed media
|
|
xor AH,AH
|
|
shl AX,1 ; AX == word offset in media table
|
|
mov BX, offset MediaTable ; BX -> Start of media table
|
|
add BX, AX ; BX -> Sensed type in media table
|
|
|
|
cmp BX, offset EndMediaTable ; Make sure we're still in the table
|
|
jge MediaSenseExit
|
|
|
|
|
|
mov SI,[BX] ; DS:SI -> Sensed device parameters
|
|
or SI,SI
|
|
je MediaSenseExit ; Unknown Media?!
|
|
|
|
lea DI, DeviceParameters.DP_BPB ; ES:DI -> Format parameters
|
|
.errnz EDP_BPB NE DP_BPB
|
|
|
|
mov CX, size A_BPB ; CX = bytes to move
|
|
cmp IsExtRAWIODrv,0
|
|
je DoIOCTL2
|
|
mov CX, size A_BF_BPB ; CX = bytes to move
|
|
DoIOCTL2:
|
|
cld
|
|
rep movsb
|
|
;
|
|
; Update the D_Cylinders. With 120mb floppies the cylinders field does change
|
|
; as opposed 720/1.44 drives
|
|
; We just back calculate the cylinders from sec/track, heads & total sectors
|
|
;
|
|
|
|
.386
|
|
push edx
|
|
push ecx
|
|
push eax
|
|
movzx eax, DeviceParameters.DP_BPB.A_BPB_Heads
|
|
movzx edx, DeviceParameters.DP_BPB.A_BPB_SectorsPerTrack
|
|
mul edx
|
|
mov ecx, eax ; save sectors per cylinder in ECX
|
|
xor eax, eax
|
|
mov ax, DeviceParameters.DP_BPB.A_BPB_TotalSectors
|
|
or ax, ax
|
|
jnz mse_sec_ok
|
|
mov eax, dword ptr DeviceParameters.DP_BPB.A_BPB_BigTotalSectors
|
|
mse_sec_ok:
|
|
div ecx ; EAX = number of cylinders
|
|
mov DeviceParameters.DP_Cylinders, ax
|
|
pop eax
|
|
pop ecx
|
|
pop edx
|
|
.8086
|
|
|
|
MediaSenseExit:
|
|
ret
|
|
|
|
MediaSense ENDP
|
|
|
|
;========================================================================
|
|
;
|
|
; TargPrm : This procedure prompts the user to insert the target disk
|
|
; into the drive.
|
|
;
|
|
;========================================================================
|
|
|
|
TargPrm PROC NEAR
|
|
|
|
mov AL, DriveToFormat
|
|
call AccessDisk
|
|
Message MsgInsertDisk
|
|
Message ContinueMsg
|
|
call USER_STRING
|
|
call CrLf
|
|
ret
|
|
|
|
TargPrm ENDP
|
|
|
|
;=========================================================================
|
|
;
|
|
; CopyToSwitchDevParams : This procedure copies the structure
|
|
; DeviceParameters into SwitchDevParams.
|
|
; Registers destroyed : CX,DI,SI
|
|
; Assumes : DS:DATA, ES:Nothing
|
|
;
|
|
;=========================================================================
|
|
|
|
CopyToSwitchDevParams proc NEAR
|
|
|
|
push DS
|
|
pop ES
|
|
|
|
mov DI,OFFSET SwitchDevParams ; ES:DI --> dest. parms
|
|
|
|
mov SI,OFFSET DeviceParameters ; DS:SI --> src. parms
|
|
|
|
mov CX,SIZE EA_DEVICEPARAMETERS ; byte transfer count
|
|
|
|
cld
|
|
rep movsb
|
|
|
|
ret
|
|
|
|
CopyToSwitchDevParams endp
|
|
|
|
;=========================================================================
|
|
;
|
|
; CompareDevParams : This procedure compares the structure
|
|
; DeviceParameters with SwitchDevParams.
|
|
; Registers destroyed : CX,DI,SI
|
|
; Assumes : DS:DATA, ES:Nothing
|
|
;
|
|
;=========================================================================
|
|
|
|
CompareDevParams proc NEAR
|
|
|
|
push DS
|
|
pop ES
|
|
|
|
mov DI,OFFSET SwitchDevParams ; ES:DI --> dest. parms
|
|
|
|
mov SI,OFFSET DeviceParameters ; DS:SI --> src. parms
|
|
|
|
mov CX,SIZE A_DEVICEPARAMETERS ; Set up count in bytes
|
|
cmp IsExtRAWIODrv,0
|
|
je DoCmp
|
|
mov CX,SIZE EA_DEVICEPARAMETERS ; Set up count in bytes
|
|
DoCmp:
|
|
cld ; Set the direction
|
|
repe cmpsb ; Compare the two BPBs
|
|
jz EqualParams ; If ZR then BPBs matched
|
|
|
|
NotEqualParams:
|
|
stc ; Signal BPBs don't match
|
|
jmp SHORT CompareParamsExit
|
|
|
|
EqualParams:
|
|
clc ; Signal BPB matches
|
|
|
|
CompareParamsExit:
|
|
ret
|
|
|
|
CompareDevParams endp
|
|
|
|
;=========================================================================
|
|
;
|
|
; LoadSwitchDevParams : This procedure copies the structure
|
|
; SwitchDevParams into DeviceParameters.
|
|
; Registers destroyed : CX,DI,SI
|
|
; Assumes : DS:DATA,ES:Nothing
|
|
;
|
|
;=========================================================================
|
|
|
|
LoadSwitchDevParams proc NEAR
|
|
|
|
push DS
|
|
pop ES
|
|
|
|
mov DI,OFFSET DeviceParameters ; ES:DI --> dest. parms
|
|
|
|
mov SI,OFFSET SwitchDevParams ; DS:SI --> src. parms
|
|
|
|
mov CX,SIZE EA_DEVICEPARAMETERS ; byte transfer count
|
|
|
|
cld
|
|
rep movsb
|
|
|
|
ret
|
|
|
|
LoadSwitchDevParams endp
|
|
|
|
;=========================================================================
|
|
;
|
|
; DetermineExistingFormat : This procedure will check if there is a
|
|
; valid format existing on the disk, in
|
|
; which case DeviceParameters will be reset
|
|
; to that format.
|
|
;
|
|
; It is assumed the destination disk is
|
|
; already in the drive.
|
|
;
|
|
; DetermineExistingFormatNoMsg : alternate entry with no message
|
|
;
|
|
;
|
|
; Calls : IsValidBpb
|
|
; ResetDeviceParameters
|
|
; DetermineCPMFormat
|
|
;
|
|
; Called by : Phase1Initialisation
|
|
;
|
|
;=========================================================================
|
|
|
|
DetermineExistingFormat proc near
|
|
|
|
push DS
|
|
push ES
|
|
Set_Data_Segment ;ensure addressibility
|
|
|
|
cmp UnformattedHardDrive,TRUE
|
|
jne @F
|
|
jmp InvalidBootRecord
|
|
|
|
@@:
|
|
Message msgCheckExistingDiskFormat
|
|
jmp short DetermineExistCommon
|
|
|
|
DetermineExistingFormatNoMsg:
|
|
|
|
push ds
|
|
push es
|
|
set_data_segment
|
|
cmp UnformattedHardDrive,TRUE
|
|
je InvalidBootRecord
|
|
|
|
DetermineExistCommon:
|
|
xor DX,DX ; Starting sector to 0
|
|
mov AL,DriveToFormat ; Set drive number
|
|
mov AH,DH ; Signal this is a read AH=0
|
|
lds BX,FatSpace ; Load transfer address
|
|
assume DS:NOTHING,ES:DATA
|
|
|
|
mov CX,2 ; # of sectors to read
|
|
; we are accessing < 32mb
|
|
mov ES:Read_Write_Relative.Start_Sector_High,0
|
|
|
|
call Read_Disk ; Disk sector read
|
|
|
|
jnc BootCheck
|
|
mov ES:RWErrorCode,AX ; Save error code (if any)
|
|
jmp InvalidbootRecord
|
|
BootCheck:
|
|
cmp word ptr [bx+3], 'SM'
|
|
jne @F
|
|
cmp word ptr [bx+5], 'MD'
|
|
jne @F
|
|
cmp word ptr [bx+7], '3F'
|
|
jne @F
|
|
mov es:RWErrorCode, 0
|
|
stc
|
|
jmp short EndDetermine
|
|
@@:
|
|
cmp BYTE PTR [BX],0e9h ; Check for JMP opcode
|
|
je TestBootSignature ; If Ok then check signature
|
|
; we can not know #reserved sectors)
|
|
cmp BYTE PTR [BX],0ebh ; Else check for SHORT jmp
|
|
jne TryCPM ; No match then not valid boot
|
|
cmp BYTE PTR [BX+2],90h ; Now check for NOP opcode
|
|
jne TryCPM ; No match then not valid boot
|
|
|
|
TestBootSignature:
|
|
ifndef NEC_98
|
|
cmp WORD PTR [BX + 510],0aa55h ; Check for 55 AA sequence
|
|
jne TryCPM ; Error if not equal
|
|
endif
|
|
|
|
CheckTheBpb:
|
|
call IsValidBpb
|
|
jc TryCPM ; CY --> Invalid format
|
|
|
|
call ResetDeviceParameters ; set DeviceParameters to
|
|
clc ; existing ones on the disk
|
|
jmp SHORT EndDetermine
|
|
|
|
TryCPM:
|
|
ifdef NEC_98
|
|
cmp ES:DeviceParameters.DP_DeviceType,DEV_HARDDISK
|
|
je InvalidBootRecord
|
|
endif
|
|
; check in case a CP/M disk is present
|
|
test ES:DeviceParameters.DP_DeviceAttributes,1
|
|
.errnz EDP_DEVICEATTRIBUTES NE DP_DEVICEATTRIBUTES
|
|
jnz InvalidBootRecord ; Bit 0=1 --> not removable
|
|
|
|
call DetermineCPMFormat
|
|
jmp SHORT EndDetermine ; CP/M disk present, DeviceParameters
|
|
; will have been modified
|
|
; Carry propagated up to
|
|
; Note: DS can be anything
|
|
|
|
InvalidBootRecord:
|
|
stc ;flag invalid format
|
|
|
|
EndDetermine:
|
|
pop ES
|
|
pop DS
|
|
|
|
ret
|
|
|
|
DetermineExistingFormat endp
|
|
|
|
;=========================================================================
|
|
;
|
|
; IsValidBpb : This procedure will inspect the BPB loaded into
|
|
; memory by the DetermineExistinFormat procedure.
|
|
;
|
|
; Input : DS:BX Buffer holding boot sector (FatSpace) ; M016
|
|
; Output : BPB is valid - NC
|
|
; BPB is invalid - CY
|
|
;
|
|
; Assumes: DS:BX: FatSpace (preserved); M016
|
|
;
|
|
;=========================================================================
|
|
|
|
IsValidBpb proc near
|
|
|
|
assume DS:NOTHING,ES:DATA
|
|
|
|
push BX ; M016; preserve BX
|
|
lea bx,[bx.bsBPB]
|
|
ifdef NEC_98
|
|
;;; It is possible NEC_98's BPB is not 200h.
|
|
cmp [BX.oldBPB.BPB_BytesPerSector],200h ; check BytesPerSector=512
|
|
je @F
|
|
cmp [BX.oldBPB.BPB_BytesPerSector],400h ; check BytesPerSector=1024
|
|
je @F
|
|
cmp [BX.oldBPB.BPB_BytesPerSector],800h ; check BytesPerSector=2048
|
|
jne NotValidBpb
|
|
@@:
|
|
else
|
|
cmp [BX.oldBPB.BPB_BytesPerSector],200h ; check BytesPerSector=512
|
|
jne NotValidBpb
|
|
endif
|
|
|
|
and [BX.oldBPB.BPB_TotalSectors],0ffffh ; check that both TotalSectors
|
|
jnz ResetBigTotalSectors ; and BigTotalSectors are not zero
|
|
and [BX.oldBPB.BPB_BigTotalSectors],0ffffh ; low word
|
|
jnz CheckMore
|
|
and [BX.oldBPB.BPB_BigTotalSectorsHigh],0ffffh ; high word
|
|
jz NotValidBpb
|
|
jmp SHORT CheckMore
|
|
|
|
ResetBigTotalSectors: ; if TotalSectors<>0 set
|
|
and [BX.oldBPB.BPB_BigTotalSectors],0h ; BigTotalSectors to zero
|
|
and [BX.oldBPB.BPB_BigTotalSectorsHigh],0h
|
|
|
|
CheckMore:
|
|
and [BX.oldBPB.BPB_SectorsPerFAT],0ffffh ; check SectorsPerFat <> 0
|
|
jnz CheckMore2
|
|
;
|
|
; Is a FAT32 BPB
|
|
;
|
|
and [BX.BGBPB_BigSectorsPerFat],0ffffh
|
|
jnz CheckMore2
|
|
and [BX.BGBPB_BigSectorsPerFatHi],0ffffh
|
|
jz NotValidBpb
|
|
CheckMore2:
|
|
cmp [BX.oldBPB.BPB_SectorsPerTrack],1h ; check 0 < SectorsPerTrack < 64
|
|
jb NotValidBpb
|
|
cmp [BX.oldBPB.BPB_SectorsPerTrack],3fh
|
|
ja NotValidBpb
|
|
|
|
cmp [BX.oldBPB.BPB_Heads],1h ; check 0 < Heads < 256
|
|
jb NotValidBpb
|
|
cmp [BX.oldBPB.BPB_Heads],0ffh
|
|
ja NotValidBpb
|
|
|
|
BpbIsValid:
|
|
clc
|
|
jmp SHORT EndIsValidBpb
|
|
|
|
NotValidBpb:
|
|
stc
|
|
|
|
EndIsValidBpb:
|
|
pop BX ; M016; restore BX
|
|
ret
|
|
|
|
IsValidBpb endp
|
|
|
|
;=========================================================================
|
|
;
|
|
; ResetDeviceParameters : This procedure will copy the BPB of the
|
|
; disk into DeviceParameters. It will also
|
|
; set the fields DP_CYLINDERS and DP_MEDIATYPE,
|
|
; for removable media.
|
|
;
|
|
; Inputs : DS:BX Boot sector held in FatSpace ; M016
|
|
; Output : Modified DeviceParameters
|
|
; Modifies: ES,SI,DI,CX,DX,BX,AX
|
|
; Assumes: DS:BX Boot sector, ES:DATA
|
|
;
|
|
;=========================================================================
|
|
|
|
ResetDeviceParameters proc near
|
|
|
|
assume DS:NOTHING,ES:DATA
|
|
|
|
lea si,[bx.bsBPB] ; Use SI instead of BX for copy
|
|
; DS:SI source BPB in buffer
|
|
|
|
;No need to modify DP_CYLINDERS,DP_MEDIATYPE
|
|
;(and DP_DEVICETYPE) for fixed disks.
|
|
|
|
ifdef NEC_98
|
|
cmp ES:DeviceParameters.DP_DeviceType,DEV_HARDDISK
|
|
je CopyBpb
|
|
endif
|
|
;use DevParms to check for removable
|
|
test ES:DeviceParameters.DP_DeviceAttributes,1
|
|
.errnz EDP_DEVICEATTRIBUTES NE DP_DEVICEATTRIBUTES
|
|
jnz CopyBpb ; Bit 0=1 --> not removable
|
|
|
|
;first compute total cylinders as
|
|
;total sectors /(sectors per track)*#heads
|
|
.386
|
|
movzx EAX,[SI.oldBPB.BPB_TotalSectors] ;get total sectors
|
|
.8086
|
|
or AX,AX ;do we need to use Big total sectors?
|
|
jnz GotTotalSectors ;don't need to if not zero
|
|
|
|
UseBigTotalSectors:
|
|
.386
|
|
mov EAX,DWORD PTR [SI.oldBPB.BPB_BigTotalSectors]
|
|
|
|
GotTotalSectors: ;now EAX has total #sectors
|
|
movzx EBX,[SI.oldBPB.BPB_SectorsPerTrack] ;get sectors per track
|
|
xor edx,edx
|
|
div EBX
|
|
.8086
|
|
xor DX,DX ;clear the remainder
|
|
mov CX,[SI.oldBPB.BPB_Heads] ;get number of heads
|
|
div CX
|
|
or DX,DX
|
|
jz CylindersOk
|
|
inc AX
|
|
|
|
;BUGBUG: Arithmetic may result in CYLINDERS being 1 less than actual value,
|
|
; for big disks (hence this calculation is skipped for fixed disks)
|
|
; PYS: fixed using same code as MSINIT.ASM
|
|
|
|
CylindersOk:
|
|
mov ES:DeviceParameters.DP_CYLINDERS,AX
|
|
.errnz EDP_CYLINDERS NE DP_CYLINDERS
|
|
|
|
;now determine DP_MEDIATYPE & DP_DEVICETYPE
|
|
|
|
mov ES:DeviceParameters.DP_MEDIATYPE,0 ; init. to zero
|
|
.errnz EDP_MEDIATYPE NE DP_MEDIATYPE
|
|
cmp AX,40 ; only 360K or less has 40 cylinders
|
|
jne CopyBpb ; MEDIATYPE has been set
|
|
|
|
cmp ES:DeviceParameters.DP_DEVICETYPE,DEV_5INCH96TPI
|
|
.errnz EDP_DEVICETYPE NE DP_DEVICETYPE
|
|
jne CopyBpb
|
|
|
|
Is360K:
|
|
mov ES:DeviceParameters.DP_MEDIATYPE,1 ; set to 1 only for 360K in 1.2M
|
|
.errnz EDP_MEDIATYPE NE DP_MEDIATYPE
|
|
|
|
|
|
;BUGBUG: Changing the value of DEVICETYPE can result in SwitchDevParams !=
|
|
; DeviceParameters, and hence a just-formatted 360K disk may not be
|
|
; recognized! -is it really necessary to set DEVICETYPE?
|
|
|
|
CopyBpb:
|
|
mov DI,OFFSET ES:DeviceParameters.DP_BPB
|
|
.errnz EDP_BPB NE DP_BPB
|
|
|
|
;ES:DI destination BPB in DeviceParameters
|
|
|
|
mov CX,SIZE BIGFATBPB ;byte transfer count
|
|
cmp [si.BPB_SectorsPerFAT],0 ;FAT32 BPB?
|
|
je @f ;Yes
|
|
|
|
mov CX,SIZE BPB ;byte transfer count
|
|
cmp byte ptr [si.bsBootSignature-bsBPB], 29h ; extended BPB ?
|
|
je @f ; Yes
|
|
mov cx,((SIZE BPB)-6) ; no, ancient small BPB
|
|
@@:
|
|
cld ;set the direction
|
|
rep movsb ;write the new BPB
|
|
ret
|
|
|
|
ResetDeviceParameters endp
|
|
|
|
;=========================================================================
|
|
;
|
|
; DetermineCPMFormat : This procedure will check the media
|
|
; descriptor in the FAT of the disk. The
|
|
; disk has a valid CP/M format if this is
|
|
; in the range FCh - FFh.
|
|
;
|
|
; Assumes : DS:BX points to boot sectors. ; M016
|
|
; Modifies : DS ; M016
|
|
; Returns : NC - Valid CP/M format detected
|
|
; DeviceParameters modified
|
|
; CY - Invalid format
|
|
;
|
|
;==========================================================================
|
|
|
|
DetermineCPMFormat proc NEAR
|
|
|
|
assume DS:NOTHING,ES:DATA
|
|
|
|
cmp ES:DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector,512
|
|
.errnz EDP_BPB NE DP_BPB
|
|
stc ; Checking default for drive
|
|
; (cannot check BPB since disk
|
|
; may not have one)
|
|
jne ExitDetCPMFormat
|
|
add BX,512 ; DS:BX points to first FAT
|
|
|
|
|
|
mov CL,BYTE PTR [BX] ; load media descriptor byte into CL
|
|
cmp CL,0fch
|
|
jb ExitDetCPMFormat ; below = carry, how practical!
|
|
|
|
Set_Data_Segment ; For the two following calls
|
|
|
|
call SetCPMParameters ; modify DeviceParameters accordingly
|
|
|
|
ExitDetCPMFormat:
|
|
ret
|
|
|
|
DetermineCPMFormat endp
|
|
|
|
;=========================================================================
|
|
;
|
|
; SetCPMParameters : This procedure copies the required BPB from the
|
|
; CP/M BPB table into DeviceParameters.BPB. Also,
|
|
; DeviceParameters.MediaType is set to 1, and
|
|
; DeviceParameters.Cylinders is set to 40.
|
|
;
|
|
; In case the disk has a 160K or 320K format, the /8
|
|
; switch is set, so that
|
|
; Returns : NC - DeviceParameters updated
|
|
; CY - Error (out of table boundaries)
|
|
;
|
|
; Modifies : AX,BX,CX,DX,SI,DI,ES
|
|
; DeviceParameters
|
|
;
|
|
; Assumes : CL contains media descriptor byte
|
|
;
|
|
;=========================================================================
|
|
|
|
SetCPMParameters proc NEAR
|
|
|
|
xor AX,AX ; find index into CP/M BPB table by
|
|
mov AL,0ffh ; subtracting media descriptor from ffh
|
|
sub AL,CL
|
|
|
|
mov BX,SIZE A_BPB ; now find byte offset by multiplying
|
|
mul BX ; by entry size
|
|
|
|
lea SI,CustomCPMBPBs
|
|
add SI,AX
|
|
cmp SI,OFFSET EndCustomCPMBPBs ; check we are still in table
|
|
ja NotInTable
|
|
|
|
lea DI,DeviceParameters.DP_BPB
|
|
.errnz EDP_BPB NE DP_BPB
|
|
|
|
mov CX,SIZE A_BPB ; set up byte transfer count
|
|
|
|
push DS ; set ES=DS
|
|
pop ES
|
|
|
|
cld ;set the direction
|
|
rep movsb ; load the BPB
|
|
|
|
mov BYTE PTR DeviceParameters.DP_MediaType,1
|
|
.errnz EDP_MEDIATYPE NE DP_MEDIATYPE
|
|
mov BYTE PTR DeviceParameters.DP_Cylinders,40
|
|
.errnz EDP_CYLINDERS NE DP_CYLINDERS
|
|
|
|
clc
|
|
jmp SHORT ExitSetCPMParm
|
|
|
|
NotInTable:
|
|
stc
|
|
|
|
ExitSetCPMParm:
|
|
ret
|
|
|
|
SetCPMParameters endp
|
|
|
|
;=========================================================================
|
|
; 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 ; Calc new BPB
|
|
|
|
Set_Data_Segment ; Set up addressibility
|
|
ifdef NEC_98
|
|
cmp DeviceParameters.DP_BPB.BPB_NumberOfFats,00h
|
|
je @F ; Yes, 0 FatS specified
|
|
|
|
cmp DeviceParameters.DP_DeviceType,DEV_HARDDISK
|
|
je $$IF101
|
|
test DeviceParameters.DP_DeviceAttributes,1
|
|
jnz $$IF101 ; Bit 0=1 --> not removable
|
|
|
|
cmp CMCDDFlag,Yes ; Memory card?
|
|
je $$IF101 ; We don't need current BPB
|
|
|
|
lea DX, DeviceParameters
|
|
mov DeviceParameters.DP_SpecialFunctions,INSTALL_FAKE_BPB
|
|
call GetDeviceParameters
|
|
jmp short $$IF101
|
|
@@:
|
|
else
|
|
; See if we have 0 Fats specified
|
|
cmp DeviceParameters.DP_BPB.oldBPB.BPB_NumberOfFats,00h
|
|
.errnz EDP_BPB NE DP_BPB
|
|
jne $$IF101 ; Yes, 0 FatS specified
|
|
endif
|
|
call Scan_Disk_Table ; Access disk table
|
|
mov BL,BYTE PTR DS:[SI+8] ; Get Fat type
|
|
mov CX,WORD PTR DS:[SI+4] ; Get Sectors/cluster
|
|
mov DX,WORD PTR DS:[SI+6] ; Number of entries for the root DIR
|
|
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_RootEntries,DX
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster,CH
|
|
ifdef NEC_98
|
|
;;
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_MediaDescriptor,Fixed_Disk
|
|
|
|
;;and ReservedSector not Fixed 1.(Large Partition)
|
|
;; reserved sector >= 1024 bytes (NEC)
|
|
|
|
cmp word ptr DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector,0200h
|
|
je $$reserved_2
|
|
cmp word ptr DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector,0100h
|
|
;Chicago is not supported 256 secters but for safely.
|
|
je $$reserved_4
|
|
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors,0001h
|
|
jmp short @F
|
|
$$reserved_2:
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors,0002h
|
|
jmp short @F
|
|
$$reserved_4:
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors,0004h
|
|
@@:
|
|
else
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector,0200h
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors,0001h
|
|
endif
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_NumberOfFats,02h
|
|
.errnz EDP_BPB NE DP_BPB
|
|
|
|
cmp BL,fBig32 ; 32-bit Fat?
|
|
jne $$IF103 ; No
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors,0020h
|
|
call Calc_Big32_Fat ; Calc Fat info
|
|
jmp SHORT $$EN102
|
|
|
|
$$IF103:
|
|
cmp BL,fBig ; 16-bit Fat?
|
|
jne $$IF102 ; no
|
|
call Calc_Big16_Fat ; Calc Fat info
|
|
jmp SHORT $$EN102
|
|
|
|
$$IF102:
|
|
call Calc_Small_Fat ; Calc small Fat info
|
|
$$EN102:
|
|
$$IF101:
|
|
ret
|
|
|
|
Set_BPB_Info ENDP
|
|
|
|
;=========================================================================
|
|
; 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
|
|
|
|
cmp DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors,00h ; small disk?
|
|
.errnz EDP_BPB NE DP_BPB
|
|
je $$IF106 ; Yes
|
|
|
|
mov DX,00h ; Set high to 0
|
|
mov AX,WORD PTR DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors
|
|
jmp SHORT $$EN106
|
|
|
|
$$IF106:
|
|
mov DX,WORD PTR DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors[+2]
|
|
mov AX,WORD PTR DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors[+0]
|
|
|
|
$$EN106:
|
|
ifdef NEC_98
|
|
call SetDiskTableNEC_98
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector,BX
|
|
cmp dx,0
|
|
je @F
|
|
mov word ptr DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors,0
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors,AX
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectorsHigh,DX
|
|
jmp short set_ok
|
|
@@:
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors,AX
|
|
mov word ptr DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors,0
|
|
mov word ptr DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectorsHigh,0
|
|
set_ok:
|
|
else
|
|
mov SI,offset DiskTable ; Point to disk data
|
|
endif
|
|
Scan:
|
|
|
|
cmp DX,WORD PTR DS:[SI] ; Below?
|
|
jb Scan_Disk_Table_Exit ; Yes, exit
|
|
ja Scan_Next ; No, continue
|
|
|
|
cmp AX,WORD PTR DS:[SI+2] ; Below or equal?
|
|
ifdef NEC_98
|
|
jb Scan_Disk_Table_Exit ; Yes, exit
|
|
else
|
|
jbe Scan_Disk_Table_Exit ; Yes, exit
|
|
endif
|
|
|
|
Scan_Next:
|
|
add SI,5*2 ; Adjust pointer
|
|
jmp Scan ; Continue scan
|
|
|
|
Scan_Disk_Table_Exit:
|
|
|
|
ret
|
|
|
|
Scan_Disk_Table ENDP
|
|
|
|
;=========================================================================
|
|
; Calc_Big32_Fat : Calculates the Sectors per Fat for a 32 bit Fat.
|
|
;
|
|
; Inputs : DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors or
|
|
; DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors
|
|
;
|
|
; Outputs : DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
|
|
; DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
|
|
; DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFatHi
|
|
; DeviceParameters.DP_BPB.BGBPB_ExtFlags
|
|
; DeviceParameters.DP_BPB.BGBPB_FS_Version
|
|
; DeviceParameters.DP_BPB.BGBPB_RootDirStrtClus
|
|
; DeviceParameters.DP_BPB.BGBPB_RootDirStrtClusHi
|
|
;
|
|
;=========================================================================
|
|
|
|
Procedure Calc_Big32_Fat
|
|
|
|
.386
|
|
; Root dir is a cluster chain on FAT32 volumes
|
|
|
|
movzx edx,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors ; EDX = Reserved
|
|
.errnz EDP_BPB NE DP_BPB
|
|
; Get total sector count
|
|
cmp DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors,00h ; Small disk?
|
|
je short $$IF109a ; Yes
|
|
movzx EAX,DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors
|
|
jmp SHORT $$EN109a
|
|
|
|
$$IF109a:
|
|
mov EAX,DWORD PTR DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors
|
|
|
|
$$EN109a:
|
|
sub EAX,EDX ; EAX = T - R
|
|
xor ebx,ebx
|
|
mov BL,DeviceParameters.DP_BPB.oldBPB.BPB_NumberOfFATs
|
|
mov BH,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
|
|
shr ebx,1 ; At 4 bytes per clus instead of 2,
|
|
; halve divisor
|
|
GotDiv1:
|
|
add EAX,EBX ; EAX = T-R-D+(256*SPC)+nFAT
|
|
dec EAX ; EAX = T-R-D+(256*SPC)+nFAT-1
|
|
xor edx,edx
|
|
div EBX ; Sec/Fat = CEIL((TOTAL-DIR-RES)/
|
|
; (((256*SECPERCLUS)+NUMFATS)/2)
|
|
|
|
mov DWORD PTR DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat,EAX
|
|
xor ax,ax
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat,ax
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_RootEntries,ax
|
|
mov DeviceParameters.DP_BPB.BGBPB_ExtFlags,ax
|
|
;
|
|
; For the moment we set the root dir start clus to 0. Later on, after
|
|
; we determine which clusters are BAD, we will set this to something
|
|
; proper.
|
|
;
|
|
mov DeviceParameters.DP_BPB.BGBPB_RootDirStrtClus,ax
|
|
mov DeviceParameters.DP_BPB.BGBPB_RootDirStrtClusHi,ax
|
|
mov DeviceParameters.DP_BPB.BGBPB_FS_Version,FAT32_Curr_FS_Version
|
|
.8086
|
|
ret
|
|
|
|
Calc_Big32_Fat ENDP
|
|
|
|
|
|
;=========================================================================
|
|
; Calc_Big16_Fat : Calculates the Sectors per Fat for a 16 bit Fat.
|
|
;
|
|
; Inputs : DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors or
|
|
; DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors
|
|
;
|
|
; Outputs : DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
|
|
;
|
|
;=========================================================================
|
|
|
|
Procedure Calc_Big16_Fat
|
|
|
|
; Get root size in sectors and add reserved to it
|
|
|
|
mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_RootEntries
|
|
.errnz EDP_BPB NE DP_BPB
|
|
mov bx,size dir_entry
|
|
mul bx ; DX:AX = bytes in root dir
|
|
mov bx,DeviceParameters.DP_BPB.oldBPB.BPB_bytesPerSector
|
|
dec bx ; Round up to sector multiple
|
|
add ax,bx
|
|
adc dx,0
|
|
inc bx ; get back sector size
|
|
div bx ; AX is sectors in root dir
|
|
mov bx,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors
|
|
add ax,bx ; AX = R + D
|
|
mov bx,ax ; over to BX
|
|
|
|
; Get Total sectors
|
|
|
|
cmp DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors,00h ; Small disk?
|
|
je $$IF109 ; Yes
|
|
|
|
xor DX,DX ; Set high to 0
|
|
mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors
|
|
jmp SHORT $$EN109
|
|
|
|
$$IF109:
|
|
mov DX,DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors[+2]
|
|
mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors[+0]
|
|
|
|
$$EN109:
|
|
sub AX,BX ; DX:AX = T - R - D
|
|
sbb DX,0
|
|
mov BL,DeviceParameters.DP_BPB.oldBPB.BPB_NumberOfFATs
|
|
mov BH,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
|
|
add AX,BX ; AX = T-R-D+(256*SPC)+nFAT
|
|
adc DX,0
|
|
sub AX,1 ; AX = T-R-D+(256*SPC)+nFAT-1
|
|
sbb DX,0
|
|
div BX ; Sec/Fat = CEIL((TOTAL-DIR-RES)/
|
|
; ((256*SECPERCLUS)+NUMFATS)
|
|
|
|
mov WORD PTR DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat,AX
|
|
ret
|
|
|
|
Calc_Big16_Fat ENDP
|
|
|
|
|
|
;=========================================================================
|
|
; Calc_Small_Fat: Calculates the Sectors per Fat for a 12 bit Fat.
|
|
;
|
|
; Inputs : DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors or
|
|
; DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors
|
|
;
|
|
; Outputs : DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
|
|
;
|
|
;=========================================================================
|
|
|
|
Procedure Calc_Small_Fat
|
|
|
|
; Get root size in sectors and add reserved to it
|
|
|
|
mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_RootEntries
|
|
.errnz EDP_BPB NE DP_BPB
|
|
mov bx,size dir_entry
|
|
mul bx ; DX:AX = bytes in root dir
|
|
mov bx,DeviceParameters.DP_BPB.oldBPB.BPB_bytesPerSector
|
|
dec bx ; Round up to sector multiple
|
|
add ax,bx
|
|
adc dx,0
|
|
inc bx ; get back sector size
|
|
div bx ; AX is sectors in root dir
|
|
mov bx,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors
|
|
add ax,bx ; AX = R + D
|
|
mov bx,ax ; over to BX
|
|
|
|
; Get total sectors
|
|
|
|
cmp DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors,00h ;small disk?
|
|
je $$IF112 ; Yes
|
|
|
|
xor DX,DX ; Set high to 0
|
|
mov AX,WORD PTR DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors
|
|
jmp SHORT $$EN112
|
|
|
|
$$IF112:
|
|
mov DX,WORD PTR DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors[+2]
|
|
mov AX,WORD PTR DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors[+0]
|
|
|
|
$$EN112:
|
|
sub AX,BX ; DX:AX = T - R - D
|
|
sbb DX,0
|
|
|
|
xor BX,BX
|
|
mov BL,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
|
|
div BX
|
|
; Now multiply by 3/2
|
|
mov BX,3
|
|
mul BX ; Div by log 2 of Sectors/clus
|
|
mov BX,2
|
|
div BX
|
|
xor DX,DX
|
|
; Now divide by 512
|
|
mov BX,512
|
|
div BX
|
|
ifdef NEC_98
|
|
or dx,dx ; for remainder
|
|
jz @F
|
|
inc AX
|
|
@@:
|
|
test ax,01h ; for even
|
|
jz @F
|
|
inc ax
|
|
@@:
|
|
cmp DeviceParameters.DP_BPB.BPB_BytesPerSector,2048
|
|
jne @F
|
|
test ax,02h ; for 2048 bytes/sector
|
|
jz @F
|
|
add ax,2
|
|
@@:
|
|
else
|
|
inc AX
|
|
; DX:AX contains number of Fat
|
|
; sectors necessary
|
|
endif
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat,AX
|
|
ret
|
|
|
|
Calc_Small_Fat ENDP
|
|
|
|
; ==========================================================================
|
|
; 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
|
|
; ==========================================================================
|
|
|
|
SetStartSector proc near
|
|
|
|
xor ax,ax
|
|
cmp DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFAT,ax
|
|
je NoRootDir
|
|
mov AX, DeviceParameters.DP_BPB.oldBPB.BPB_RootEntries
|
|
.errnz EDP_BPB NE DP_BPB
|
|
mov BX, size dir_entry
|
|
mul BX ; DX:AX is bytes in root dir
|
|
mov bx, DeviceParameters.DP_BPB.oldBPB.BPB_bytesPerSector
|
|
dec bx ; Round up to sector multiple
|
|
add ax,bx
|
|
adc dx,0
|
|
inc bx ; Get sector size back
|
|
div bx ; AX = Sectors in root dir
|
|
NoRootDir:
|
|
mov SectorsInRootDirectory,AX
|
|
.386
|
|
movzx eax,ax
|
|
mov StartSector, EAX ;not done yet!
|
|
|
|
; Calculate the number of Fat Sectors
|
|
|
|
movzx EAX, DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
|
|
or ax,ax
|
|
jnz short NotFat32a
|
|
mov EAX, DWORD PTR DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
|
|
NotFat32a:
|
|
movzx ebx,DeviceParameters.DP_BPB.oldBPB.BPB_numberOfFats
|
|
mul ebx
|
|
; add in the number of boot Sectors
|
|
movzx ebx,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors
|
|
|
|
add EAX,EBX
|
|
add StartSector, EAX
|
|
.8086
|
|
return
|
|
|
|
SetStartSector endp
|
|
|
|
; ==========================================================================
|
|
;
|
|
; fBigFat = ( ( (TotalSectors - StartSector) / SectorsPerCluster) >= 4086 )
|
|
;
|
|
; ==========================================================================
|
|
|
|
SetfBigFat proc near
|
|
|
|
cmp DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFAT,0
|
|
.errnz EDP_BPB NE DP_BPB
|
|
jne NotFat32b
|
|
mov fBig32Fat, TRUE ; Set flag
|
|
mov ThisSysInd,8
|
|
jmp SHORT $$EN21
|
|
|
|
NotFat32b:
|
|
cmp DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors+2,0
|
|
je $$IF21 ; no, 12-bit Fat
|
|
mov fBigFat, TRUE ; Set flag
|
|
mov ThisSysInd,6
|
|
jmp SHORT $$EN21 ; Nope, < 32,b
|
|
|
|
$$IF21: ; Assume this used
|
|
mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors
|
|
cmp AX,0 ; Was this field used?
|
|
jne $$IF23 ; Yes
|
|
; No, use other sector field
|
|
mov AX, DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors
|
|
$$IF23: ; ** Fix for PTM PCDOS P51
|
|
mov ThisSysInd,1 ; Set small Fat for default
|
|
sub AX,word ptr StartSector ; Get Sectors in data area
|
|
xor DX,DX
|
|
xor BX,BX
|
|
mov bl,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
|
|
div BX ; Get total clusters
|
|
|
|
cmp AX,BIG_Fat_THRESHOLD ; Is clusters >= 4086?
|
|
jnae $$IF25
|
|
|
|
mov fBigFat,TRUE ; 16 bit Fat if >=4096
|
|
; ** END fix for PTM PCDOS P51
|
|
mov ThisSysInd,4 ; set large Fat
|
|
$$IF25:
|
|
$$EN21:
|
|
return
|
|
|
|
SetfBigFat endp
|
|
|
|
;==========================================================================
|
|
;
|
|
; GetTotalClusters : This procedure initializes the variable TotalClusters.
|
|
; This is utilized by Quick Format to check for when all
|
|
; the clusters have been processed.
|
|
; Destroys : AX,BX,CX,DX
|
|
; Strategy : TotalClusters = (TotalSectors-Fats-Root-Reserved)/SectorsPerCluster
|
|
;
|
|
;==========================================================================
|
|
|
|
GetTotalClusters proc NEAR
|
|
|
|
.386
|
|
movzx EAX,DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors
|
|
.errnz EDP_BPB NE DP_BPB
|
|
or AX,AX ; Check if BigTotalSectors must be used
|
|
jnz short GoSubstract ; M015; Substrack Fats, Root and reserved
|
|
|
|
GetBigSectors:
|
|
mov EAX,dword ptr DeviceParameters.DP_BPB.oldBPB.BPB_BigTotalSectors
|
|
|
|
GoSubstract:
|
|
movzx edx,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors
|
|
sub EAX,EDX
|
|
|
|
movzx edx,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
|
|
or dx,dx
|
|
jnz short NotFat32c
|
|
mov DeviceParameters.DP_BPB.oldBPB.BPB_RootEntries,dx ; No root dir on FAT32
|
|
mov edx,dword ptr DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
|
|
NotFat32c:
|
|
movzx cx,DeviceParameters.DP_BPB.oldBPB.BPB_NumberOfFats
|
|
jcxz GoDivide ; M017; if non fat, don't even do the root
|
|
|
|
SubstractAFat:
|
|
sub EAX,EDX
|
|
loop SubstractAFat
|
|
|
|
GoSubstractRoot:
|
|
; Assumes that BytesPerSectors is a power of 2 and at least 32
|
|
; Those are valid assumptions since BIOS requires the same.
|
|
|
|
mov BX,DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
|
|
shr BX,5 ; divide by 32, BX = root entries per sector (a power of 2)
|
|
|
|
or BX,BX ; Sanity check for infinite looping
|
|
jz short SayWhat
|
|
|
|
mov CX,DeviceParameters.DP_BPB.oldBPB.BPB_RootEntries
|
|
|
|
SubstractRootLoop:
|
|
test BX,1
|
|
jnz short SubstractRootReady
|
|
shr BX,1
|
|
shr CX,1
|
|
jmp short SubstractRootLoop
|
|
|
|
SubstractRootReady:
|
|
movzx ecx,cx
|
|
|
|
sub EAX,ECX
|
|
GoDivide:
|
|
movzx ebx,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
|
|
xor edx,edx
|
|
div EBX
|
|
|
|
inc EAX ; Bump by 1 since start with 2
|
|
cmp DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat,0
|
|
je short NoOvlChk
|
|
cmp EAX,0000FFEFh ; Sanity check
|
|
ja short SayWhat
|
|
NoOvlChk:
|
|
mov TotalClusters,EAX
|
|
.8086
|
|
ret
|
|
|
|
SayWhat:
|
|
Message msgInvalidDeviceParameters
|
|
jmp FatalExit
|
|
|
|
GetTotalClusters endp
|
|
|
|
; SetDOS_Dpb - Need to set the DPB for a memory card because the
|
|
; default will be for the last disk accessed in the
|
|
; the drive and may not be correct for the current
|
|
; disk.
|
|
|
|
SetDOS_Dpb PROC
|
|
|
|
cmp CMCDDFlag, Yes
|
|
je @f
|
|
clc
|
|
ret
|
|
|
|
@@:
|
|
push ds
|
|
pop es
|
|
mov di, offset SetDPBPacket
|
|
mov ax, OFFSET DeviceParameters.DP_BPB ; DS:AX --> BPB for disk
|
|
.errnz EDP_BPB NE DP_BPB
|
|
mov word ptr [di.SetDPB_Value1],ax
|
|
mov word ptr [di.SetDPB_Value1+2],ds
|
|
xor ax,ax
|
|
mov word ptr [di.SetDPB_Value2],ax
|
|
mov word ptr [di.SetDPB_Value2+2],ax
|
|
mov word ptr [di.SetDPB_Value3],ax
|
|
mov word ptr [di.SetDPB_Value3+2],ax
|
|
mov word ptr [di.SetDPB_Value4],ax
|
|
mov word ptr [di.SetDPB_Value4+2],ax
|
|
.386
|
|
mov [di.SetDPB_Function],SetDPB_SetDPBFrmBPB
|
|
movzx dx,DriveToFormat
|
|
.8086
|
|
inc dx ; 1 based drive number
|
|
mov ax,(Get_Set_DriveInfo SHL 8) OR Set_DPBForFormat
|
|
mov cx,size SDPDFormatStruc
|
|
int 21h
|
|
;
|
|
; NOTE: This call fails in protected mode under Win95. VFAT/VDEF do not
|
|
; implement it. This call REALLY isn't necessary anyway. The
|
|
; SetDeviceParameters we do as part of the format is supposed to
|
|
; trigger the device driver to return "media changed" on the next
|
|
; media check call.
|
|
;
|
|
clc
|
|
|
|
ret
|
|
|
|
SetDOS_Dpb ENDP
|
|
|
|
;==========================================================================
|
|
ifdef NEC_98
|
|
; IN : DX:AX total_sectors
|
|
; : DeviceParameters
|
|
; OUT : SI = offset DiskTable
|
|
; : BX = BytesPerSector
|
|
; : DX:AX = total sectors
|
|
;
|
|
; USE : AX,BX,DX,SI
|
|
;
|
|
SetDiskTableNEC_98 proc near
|
|
|
|
mov bx,DeviceParameters.DP_BPB.BPB_BytesPerSector
|
|
|
|
cmp bx,200h
|
|
je large?_512
|
|
cmp bx,100h
|
|
je large?_256
|
|
cmp bx,400h
|
|
jne not_large
|
|
|
|
large?_1024:
|
|
cmp dx,2
|
|
jb not_large
|
|
je @F
|
|
jmp set_large1024 ; 1024 and DX > 2 --> large partition.
|
|
; > 129MB
|
|
|
|
@@:
|
|
cmp ax,200h
|
|
jb not_large
|
|
jmp set_large1024 ; 1024 and DX = 2 and AX >= 512 --> large partition.
|
|
; > 128.5MB
|
|
|
|
large?_512:
|
|
cmp dx,4
|
|
jb not_large
|
|
je @F
|
|
jmp set_large512 ; 512 and DX > 4 --> large partition.
|
|
; > 129MB
|
|
|
|
@@:
|
|
cmp ax,400h
|
|
jb not_large
|
|
jmp set_large512 ; 512 and DX = 4 and AX >= 1024 --> large partition.
|
|
; > 128.5MB
|
|
|
|
large?_256:
|
|
cmp dx,8
|
|
jb not_large
|
|
je @F
|
|
jmp set_large256 ; 256 and DX > 8 --> large partition.
|
|
; > 129MB
|
|
|
|
@@:
|
|
cmp ax,800h
|
|
jb not_large
|
|
jmp set_large256 ; 256 and DX = 8 and AX >= 2048 --> large partition.
|
|
; > 128.5MB
|
|
|
|
not_large:
|
|
cmp bx,800h
|
|
jne @F
|
|
jmp set_2K
|
|
|
|
@@:
|
|
cmp bx,200h
|
|
je sec2K?_512
|
|
cmp bx,100h
|
|
je sec2K?_256
|
|
|
|
sec2K?_1024:
|
|
cmp dx,1
|
|
jb not_2K
|
|
je @F
|
|
|
|
shr dx,1 ;convert 1K->2K
|
|
rcr ax,1
|
|
jmp set_2K ; 1024 and DX > 1 --> 2KB partition.
|
|
; > 65MB
|
|
|
|
@@:
|
|
cmp ax,200h
|
|
jb not_2K
|
|
shr dx,1 ;convert 1K->2K
|
|
rcr ax,1
|
|
jmp set_2K ; 1024 and DX = 1 and AX >= 1024 --> 2KB partition.
|
|
; > 64.5MB
|
|
|
|
sec2K?_512:
|
|
cmp dx,2
|
|
jb not_2K
|
|
je @F
|
|
shr dx,1 ;convert 512->2K
|
|
rcr ax,1
|
|
shr dx,1
|
|
rcr ax,1
|
|
jmp set_2K ; 512 and DX > 2 --> 2KB partition.
|
|
; > 65MB
|
|
|
|
@@:
|
|
cmp ax,400h
|
|
jb not_2K
|
|
shr dx,1 ;convert 512->2K
|
|
rcr ax,1
|
|
shr dx,1
|
|
rcr ax,1
|
|
jmp set_2K ; 512 and DX = 2 and AX >= 1024 --> 2KB partition.
|
|
; > 64.5MB
|
|
|
|
sec2K?_256:
|
|
cmp dx,4
|
|
jb not_2K
|
|
je @F
|
|
shr dx,1 ;convert 256->2K
|
|
rcr ax,1
|
|
shr dx,1
|
|
rcr ax,1
|
|
shr dx,1
|
|
rcr ax,1
|
|
shr dx,1
|
|
rcr ax,1
|
|
jmp set_2K ; 256 and DX > 4 --> 2KB partition.
|
|
; > 65MB
|
|
|
|
@@:
|
|
cmp ax,800h
|
|
jb not_2K
|
|
shr dx,1 ;convert 256->2K
|
|
rcr ax,1
|
|
shr dx,1
|
|
rcr ax,1
|
|
shr dx,1
|
|
rcr ax,1
|
|
shr dx,1
|
|
rcr ax,1
|
|
jmp set_2K ; 256 and DX = 4 and AX >= 1024 --> 2KB partition.
|
|
; > 64.5MB
|
|
|
|
not_2K:
|
|
push cx
|
|
push dx
|
|
push ax
|
|
xor dx,dx
|
|
mov ax,1024
|
|
div bx
|
|
mov cx,ax
|
|
pop ax ;DX:AX total sectors
|
|
pop dx
|
|
@@:
|
|
shr cx,1
|
|
jc @F
|
|
shr dx,1
|
|
rcr ax,1
|
|
jmp short @B
|
|
pop cx ;DX:AX convert ->1KB
|
|
|
|
mov bx,1024
|
|
cmp dx,0
|
|
je @F
|
|
mov ax,0FFFFh
|
|
mov dx,0
|
|
@@:
|
|
;;; follow function is NEC_98 only.
|
|
push ax
|
|
push ds
|
|
push dx
|
|
push cx
|
|
|
|
push cs
|
|
pop ds
|
|
mov dx,offset LPTABLE
|
|
mov cl,13h
|
|
int 220 ;GET LPTABLE
|
|
|
|
add dx,001Ah ;EXLPTABLE start offset
|
|
mov al,DriveToFormat
|
|
shl al,1 ;Drive * 2
|
|
xor ah,ah
|
|
add dx,ax
|
|
inc dx ;+1 (=DA/UA)
|
|
mov bx,dx
|
|
mov al,[bx] ;GET DA/UA at al
|
|
pop cx
|
|
pop dx
|
|
pop ds
|
|
mov ah,al ;al copy to ah
|
|
and al,0F0h
|
|
cmp al,80h
|
|
je @F
|
|
jmp set_SCSItable ;STACK AX ;Not 8xh
|
|
|
|
@@:
|
|
push es
|
|
push ax
|
|
mov ax,40h
|
|
mov es,ax ;es = 0040h
|
|
pop ax
|
|
mov al,es:[0057h]
|
|
pop es
|
|
cmp ah,80h
|
|
je IDE1_check ;STACK AX
|
|
and al,00000111b
|
|
cmp al,00000110b
|
|
je set_SASItable ;STACK AX 2nd IDE is 40MB
|
|
cmp al,00000100b
|
|
je set_SASItable ;STACK AX 2nd IDE is 20MB
|
|
jmp short set_SCSItable ;STACK AX
|
|
IDE1_check:
|
|
and al,00111000b
|
|
cmp al,00110000b
|
|
je set_SASItable ;STACK AX 1st IDE is 40MB
|
|
cmp al,00100000b
|
|
je set_SASItable ;STACK AX 1st IDE is 20MB
|
|
jmp short set_SCSItable ;STACK AX
|
|
|
|
LPTABLE DB 96 DUP (?)
|
|
|
|
set_SASItable:
|
|
pop ax
|
|
mov si, offset SASI1024Table
|
|
jmp short exit_disktable
|
|
set_large1024:
|
|
set_SCSItable:
|
|
pop ax
|
|
mov si, offset SCSI1024Table
|
|
jmp short exit_disktable
|
|
set_large256:
|
|
mov si, offset Large256Table
|
|
jmp short exit_disktable
|
|
set_large512:
|
|
mov si, offset Large512Table
|
|
jmp short exit_disktable
|
|
set_2K:
|
|
mov bx,2048
|
|
cmp dx,0
|
|
je @F
|
|
mov ax,0FFFFh
|
|
mov dx,0
|
|
@@:
|
|
mov si, offset Small2048Table
|
|
|
|
exit_disktable:
|
|
ret
|
|
SetDiskTableNEC_98 endp
|
|
|
|
MY_INT24 proc far
|
|
mov al, 0 ; don't display messages
|
|
iret
|
|
MY_INT24 endp
|
|
|
|
endif
|
|
|
|
CODE ENDS
|
|
|
|
END
|
|
|