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

  1. ;/*
  2. ; * Microsoft Confidential
  3. ; * Copyright (C) Microsoft Corporation 1991
  4. ; * All Rights Reserved.
  5. ; */
  6. ;===========================================================================
  7. ;
  8. ; FILE: DSKFRMT.ASM
  9. ;
  10. ;===========================================================================
  11. ;===========================================================================
  12. ;Declaration of include files
  13. ;===========================================================================
  14. debug equ 0
  15. .xlist
  16. INCLUDE DOSEQUS.INC
  17. INCLUDE DOSMAC.INC
  18. INCLUDE SYSCALL.INC
  19. INCLUDE ERROR.INC
  20. INCLUDE BPB.INC
  21. INCLUDE FOREQU.INC
  22. INCLUDE FORMACRO.INC
  23. INCLUDE IOCTL.INC
  24. INCLUDE FORSWTCH.INC
  25. .list
  26. ;===========================================================================
  27. ; Declarations for all publics in other modules used by this module
  28. ;===========================================================================
  29. ;===========================================================================
  30. ; Data segment
  31. ;===========================================================================
  32. DATA SEGMENT PUBLIC PARA 'DATA'
  33. ;Bytes
  34. EXTRN fBigFat :BYTE
  35. EXTRN fBig32Fat :BYTE
  36. EXTRN ExitStatus :BYTE
  37. EXTRN DblFlg :BYTE
  38. EXTRN DriveToFormat :BYTE
  39. EXTRN msgFormatFailure :BYTE
  40. EXTRN msgDiskUnusable :BYTE
  41. EXTRN msgNotSystemDisk :BYTE
  42. EXTRN msgParametersNotSupported:BYTE
  43. EXTRN msgParametersNotSupportedByDrive:BYTE
  44. EXTRN msgHardDiskWarning :BYTE
  45. EXTRN msgDiskWarning :BYTE
  46. EXTRN msgInsertDisk :BYTE
  47. EXTRN msgCrLf :BYTE
  48. EXTRN msgCurrentTrack :BYTE
  49. EXTRN msgFormatComplete :BYTE
  50. EXTRN msgVerify :BYTE
  51. EXTRN msgSetBadClus :BYTE
  52. EXTRN msgSetBadClusDone :BYTE
  53. EXTRN ContinueMsg :BYTE
  54. EXTRN Extended_Error_Msg :BYTE
  55. EXTRN Clustbound_Flag :BYTE
  56. EXTRN Fatal_Error :BYTE
  57. EXTRN FATNotAllInMem :BYTE
  58. EXTRN msgInsufficientMemory :BYTE
  59. EXTRN msgWriteFat :BYTE
  60. ;Words
  61. EXTRN FirstHead :WORD
  62. EXTRN FirstCylinder :WORD
  63. EXTRN Formatted_Tracks_Low :WORD
  64. EXTRN Formatted_Tracks_High :WORD
  65. EXTRN Paras_Per_Fat :WORD
  66. EXTRN SwitchMap :WORD
  67. EXTRN SwitchMap2 :WORD
  68. EXTRN Relative_Sector_Low :WORD
  69. EXTRN Relative_Sector_High :WORD
  70. EXTRN Clustbound_Buffer_Seg :WORD
  71. EXTRN Clustbound_Adj_Factor :WORD
  72. EXTRN Clustbound_Spt_Count :WORD
  73. ; Dwords
  74. EXTRN TracksLeft :DWORD
  75. EXTRN TracksPerDisk :DWORD
  76. EXTRN sector_in_buffer :DWORD
  77. EXTRN sector_to_read :DWORD
  78. EXTRN TotalClusters :DWORD
  79. EXTRN StartSector :DWORD
  80. EXTRN FATSecCntInMem :DWORD
  81. ;Pointers
  82. EXTRN SysSiz :DWORD
  83. EXTRN BioSiz :DWORD
  84. EXTRN Msg_Allocation_Unit_Val :DWORD
  85. EXTRN FatSpace :DWORD
  86. EXTRN FatSector :DWORD
  87. ;Structures
  88. EXTRN DeviceParameters :BYTE
  89. EXTRN IsExtRAWIODrv :BYTE
  90. EXTRN FormatPacket :BYTE
  91. EXTRN Read_Write_Relative :BYTE
  92. RWPacket a_TrackReadWritePacket <>
  93. ifdef NEC_98
  94. RW_TRF_Area db 2048 dup(0)
  95. else
  96. RW_TRF_Area db 512 dup(0)
  97. endif
  98. fLastChance db FALSE ; Flags reinvocation from
  99. ; LastChanceToSaveIt. Used by DskPrm
  100. FormatError db 0
  101. Format_End db FALSE
  102. Track_Action db ? ; Actual operation performed on disk
  103. odd_entry db 1 ; flag for 12-bit FAT entry alignment
  104. entry_offset dw ? ; Offset of entry from start of sector
  105. PercentComplete dw 0FFFFh ; Init non-zero so msg will display
  106. ; first time
  107. Fat_Init_Value dw 0 ; initializes the Fat
  108. SysTrks dd ?
  109. Sectors dw ?
  110. CurrentHead dw 0
  111. CurrentCylinder dw 0
  112. Tracks_To_Format dw ?
  113. Track_Count dw ?
  114. CurrentCluster dd ? ; holds the cluster currently being checked
  115. ; in QuickFormat
  116. BadClusValue dd ? ; holds FAT entry value for bad cluster
  117. BadClusBitMap dd 0
  118. CurrFATInMemStartSec dd 0
  119. CurrFATInMemSecCnt dd 0
  120. CurrFATInMemStartClus dd 0
  121. FATInMemClusCnt dd 0
  122. DATA ENDS
  123. ;===========================================================================
  124. ; Executable code segment
  125. ;===========================================================================
  126. CODE SEGMENT PUBLIC PARA 'CODE'
  127. ASSUME CS:CODE, DS:DATA, ES:DATA
  128. ;===========================================================================
  129. ;EXTRNs needed in code segment
  130. ;===========================================================================
  131. ;Labels
  132. EXTRN FatalExit :NEAR
  133. EXTRN CrLf :NEAR
  134. ;Functions
  135. EXTRN DetermineExistingFormatNoMsg :NEAR
  136. EXTRN SetStartSector :NEAR
  137. EXTRN SetfBigFat :NEAR
  138. EXTRN Phase2Initialization :NEAR
  139. EXTRN GetBioSize :NEAR
  140. EXTRN GetDosSize :NEAR
  141. EXTRN GetCmdSize :NEAR
  142. EXTRN LastChanceToSaveIt :NEAR
  143. EXTRN AccessDisk :NEAR
  144. EXTRN Yes? :NEAR
  145. EXTRN ExitProgram :NEAR
  146. EXTRN User_String :NEAR
  147. EXTRN Read_Disk :NEAR
  148. EXTRN Seg_Adj :NEAR
  149. EXTRN IsDblSpaceDisk :NEAR
  150. EXTRN Write_Disk :NEAR
  151. EXTRN ShowFormatSize :NEAR
  152. ;Constants
  153. EXTRN EXIT_FATAL :ABS
  154. EXTRN EXIT_NO :ABS
  155. EXTRN EXIT_DRV_NOT_READY :ABS
  156. EXTRN EXIT_WRIT_PROTECT :ABS
  157. EXTRN EXIT_FATAL :ABS
  158. EXTRN EXIT_NO :ABS
  159. ;===========================================================================
  160. ; Declarations for all publics in this module
  161. ;===========================================================================
  162. PUBLIC Disk_Format_Proc
  163. PUBLIC FrmtProb
  164. PUBLIC fLastChance
  165. PUBLIC CurrentHead
  166. PUBLIC CurrentCylinder
  167. PUBLIC Multiply_32_Bits
  168. PUBLIC SetDeviceParameters
  169. PUBLIC PercentComplete
  170. PUBLIC Prompt_User_For_Disk
  171. PUBLIC calc_sector_and_offset
  172. PUBLIC ReadFatSector
  173. PUBLIC GetSetFatEntry
  174. PUBLIC GetFatSectorEntry
  175. PUBLIC DetermineTrackAction
  176. PUBLIC QuickFormat
  177. PUBLIC FlushFATBuf
  178. PUBLIC Fat_Init
  179. PUBLIC Get_Bad_Sector_Hard
  180. PUBLIC Multiply_32_Bits
  181. PUBLIC IsThisClusterBad
  182. PUBLIC WrtEOFMrkInRootClus
  183. ;========================================================================
  184. ;
  185. ; DISK_FORMAT_PROC : This procedure is used to call
  186. ; the real DiskFormat procedure.
  187. ; Returns : NC --> Format successful
  188. ; CY --> Format unsuccessful, go to next disk
  189. ;
  190. ;========================================================================
  191. Disk_Format_Proc proc near
  192. call DetermineTrackAction ; Check for safe format, and validity
  193. ; of quick format switch
  194. call init_fat_with_header ; setup blank FAT image
  195. test SwitchMap,SWITCH_Q ; Check for quick format
  196. jz RegularFormat
  197. test SwitchMap,SWITCH_Z ; Check for sec/clus override
  198. jnz RegularFormat
  199. call ShowFormatSize ; size being formatted message
  200. call QuickFormat
  201. jc FarExit ; procedure exit is too far for direct jump
  202. Message msgFormatComplete
  203. FarExit:
  204. jmp Exit_Disk_Format_Proc
  205. RegularFormat:
  206. test SwitchMap,SWITCH_Z
  207. jnz no_load_old_fat ; don't need to load the old FAT
  208. test SwitchMap2,Switch2_C
  209. jnz no_load_old_fat ; don't need to load the old FAT
  210. call SetUpBadClusTransfer
  211. jnc no_load_old_fat
  212. Message msgInsufficientMemory
  213. stc
  214. jmp short FarExit
  215. no_load_old_fat:
  216. call ShowFormatSize ; size being formatted message
  217. call DiskFormat ; Format the disk
  218. jnc GetTrk ; check for problems
  219. FrmtProb:
  220. test SwitchMap,Switch_Select ; SELECT option?
  221. jnz CheckForMore ; No - display message
  222. Message msgFormatFailure
  223. mov ExitStatus, EXIT_FATAL
  224. CheckForMore:
  225. stc ; Signal error which will be handled
  226. ; in main routine (by prompting for
  227. ; next disk)
  228. jmp Exit_Disk_Format_Proc
  229. ;Mark any bad Sectors in the Fats
  230. ;And keep track of how many bytes there are in bad Sectors
  231. GetTrk:
  232. call BadSector ; Do bad track fix-up
  233. jc FrmtProb ; Had an error in Fmt - can't recover
  234. CMP AX,0 ; Are we finished?
  235. jnz TrkFnd ; No - check error conditions
  236. jmp Exit_Disk_Format_Proc ; Yes
  237. ;--------------------------------------------------------------------------
  238. ; BUG NOTE: The two sections in "if ibmcopyright..." here and below are
  239. ; to correct a bug. If one of the Sectors just above the 32M boundary
  240. ; were bad, it thought they were in the system area, and hence that the
  241. ; disk was unusable.
  242. ;
  243. ; PYS: IBMCOPYRIGHT removed
  244. ;
  245. ;--------------------------------------------------------------------------
  246. TrkFnd:
  247. .386
  248. mov EBX,dword ptr Relative_Sector_Low ; get the sector
  249. cmp EBX,StartSector ; Any sec in the sys area bad?
  250. .8086
  251. jae ClrTest ; MZ 2.26 unsigned compare
  252. Message msgDiskUnusable
  253. jmp FrmtProb ; Bad disk -- try again
  254. ClrTest:
  255. mov Sectors,AX ; Save # sectors on the track
  256. test SwitchMap,SWITCH_S ; If sys requested calc size
  257. jz Bad100
  258. cmp BYTE PTR DblFlg,0 ; Is sys space aready calced?
  259. jnz cmpTrks ; Yes - all ready for the compare
  260. inc BYTE PTR DblFlg ; No - set the flag
  261. call GetBioSize ; Get the size of the Bios
  262. mov DX,WORD PTR SysSiz+2
  263. mov AX,WORD PTR SysSiz
  264. mov WORD PTR BioSiz+2,DX
  265. mov WORD PTR BioSiz,AX
  266. call GETDOSSIZE
  267. call GETCMDSIZE
  268. mov DX,WORD PTR BioSiz+2
  269. mov AX,WORD PTR BioSiz
  270. div DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
  271. .errnz EDP_BPB NE DP_BPB
  272. .386
  273. movzx eax,ax
  274. add EAX,StartSector
  275. mov SysTrks,EAX ; Space Fat,Dir,and system
  276. ; files require
  277. cmpTrks:
  278. mov EBX,dword ptr Relative_Sector_Low ;get the low word of the sector
  279. cmp EBX,SysTrks
  280. .8086
  281. JA Bad100 ; MZ 2.26 unsigned compare
  282. mov ExitStatus, EXIT_FATAL
  283. Message msgNotSystemDisk
  284. AND SwitchMap,NOT SWITCH_S ; Turn off system transfer switch
  285. mov WORD PTR SysSiz+2,0 ; No system to transfer
  286. mov WORD PTR SysSiz,0 ; No system to transfer
  287. Bad100:
  288. cmp DeviceParameters.DP_DeviceType, DEV_HARDDISK ;hard disk?
  289. .errnz EDP_DEVICETYPE NE DP_DEVICETYPE
  290. jne $$IF5 ; no
  291. call Get_Bad_Sector_Hard ; see if a sector is bad
  292. jmp SHORT $$EN5
  293. $$IF5:
  294. call Get_Bad_Sector_Floppy ; mark entire track bad
  295. $$EN5:
  296. jmp GetTrk
  297. Exit_Disk_Format_Proc:
  298. ret
  299. Disk_Format_Proc ENDP
  300. ;==========================================================================
  301. ;
  302. ; DetermineTrackAction : This procedure sets the value of
  303. ; Track_Action based on the setting of
  304. ; SWITCH_U, the unconditional format switch.
  305. ; Track_Action is the function that is
  306. ; actually performed on each track of the
  307. ; disk to be formatted.
  308. ;
  309. ; Inputs : SwitchMap
  310. ; Output : SWITCH_U set - Track_Action = Format and Verify
  311. ; SWITCH_U clear - Track_Action = Verify only
  312. ;
  313. ;==========================================================================
  314. DetermineTrackAction proc near
  315. test SwitchMap,SWITCH_U
  316. jz Verify_Only
  317. Format_And_Verify:
  318. mov Track_Action,FORMAT_TRACK ; regular format
  319. ret
  320. Verify_Only:
  321. mov Track_Action,VERIFY_TRACK ; safe format
  322. ret
  323. DetermineTrackAction endp
  324. ; =========================================================================
  325. ; DiskFormat:
  326. ; Format the tracks on the disk
  327. ; Since we do our SetDeviceParameters here, we also need to
  328. ; detect the legality of /N /T if present and abort with errors
  329. ; if not.
  330. ; This routine stops as soon as it encounters a bad track
  331. ; Then BadSector is called to report the bad track, and it continues
  332. ; the format
  333. ;
  334. ; Algorithm:
  335. ; current track = first
  336. ; while not done
  337. ; if format track fails
  338. ; DiskFormatErrors = true
  339. ; return
  340. ; next track
  341. ; =========================================================================
  342. DiskFormat proc near
  343. mov DeviceParameters.DP_SpecialFunctions, (INSTALL_FAKE_BPB or TRACKLAYOUT_IS_GOOD)
  344. .errnz EDP_SPECIALFUNCTIONS NE DP_SPECIALFUNCTIONS
  345. lea DX, DeviceParameters
  346. call SetDeviceParameters
  347. test SwitchMap,switch_8 ; DCL 5/12/86 avoid Naples AH=18h
  348. jnz stdBpB ; lackof support for 8 Secs/track
  349. ; DCL 5/12/86 - Always do the Status_FOR_FORMAT test, as we
  350. ; don't know if the machine has this support. For 3.2 /N:
  351. ; & /T: were not documented & therefore not fully supported
  352. ; thru the ROM of Aquarius & Naples & Royal Palm
  353. ; test SwitchMap, SWITCH_N or SWITCH_T ; IF (/N or /T)
  354. ; jz StdBPB
  355. ; THEN check if
  356. ; supported
  357. ; Check to see if device driver can handle specified parameters
  358. mov FormatPacket.FP_SpecialFunctions, Status_FOR_FORMAT
  359. mov AX, (IOCTL shl 8) or GENERIC_IOCTL
  360. mov BL, DriveToFormat
  361. inc BL
  362. mov CX, (RAWIO shl 8) or FORMAT_TRACK
  363. cmp IsEXTRAWIODrv,0
  364. je DoFrmt
  365. mov CX, (EXTRAWIO shl 8) or FORMAT_TRACK
  366. DoFrmt:
  367. lea DX, FormatPacket
  368. int 21h
  369. ;;%out FORQUICK ENABLED!!!!!
  370. ;; clc ;**ARR
  371. ; switch ( FormatStatusCall)
  372. ; cmp FormatPacket.FP_SpecialFunctions, \
  373. ; Format_No_ROM_Support
  374. ; jb NTSupported ; 0 returned from IBMBIO
  375. ; ja IllegalComb ; 2 returned - ROM Support
  376. ; Illegal Combination!
  377. cmp FormatPacket.FP_SpecialFunctions,0 ; 0 --> Can support
  378. je NTSupported
  379. cmp FormatPacket.FP_SpecialFunctions,2 ; 2 --> Cannot support
  380. jne $$IF28
  381. Message msgParametersNotSupportedByDrive
  382. mov Fatal_Error,Yes ; Indicate quittin'type err!
  383. jmp SHORT $$EN28
  384. $$IF28:
  385. cmp FormatPacket.FP_SpecialFunctions,3 ; 3 --> No disk in drive
  386. jne $$IF30
  387. mov AX,Error_Not_Ready ; flag not ready
  388. call CheckError ; set error level
  389. jmp FrmtProb ; exit program
  390. jmp SHORT $$EN30 ; DCL No ROM support is okay
  391. $$IF30:
  392. ; except for /N: & /T:
  393. test SwitchMap, SWITCH_N or SWITCH_T ; DCL 5/12/86
  394. jz $$IF32
  395. Message msgParametersNotSupported
  396. mov Fatal_Error,Yes ; Indicate quittin 'type err!
  397. $$IF32:
  398. $$EN30:
  399. $$EN28:
  400. cmp Fatal_Error,Yes
  401. jne StdBPB
  402. jmp FatalExit
  403. ; We have the support to carry
  404. ; out the FORMAT
  405. NTSupported:
  406. StdBPB:
  407. mov FormatPacket.FP_SpecialFunctions, 0
  408. mov AX, FirstHead
  409. mov FormatPacket.FP_Head, AX
  410. mov AX, FirstCylinder
  411. mov FormatPacket.FP_Cylinder, AX
  412. ;M018 - begin
  413. mov AX, word ptr TracksPerDisk
  414. mov word ptr TracksLeft, AX
  415. mov AX, word ptr TracksPerDisk+2
  416. mov word ptr TracksLeft+2, AX
  417. ;M018 - end
  418. mov Format_End,False ; flag not at end of format
  419. call Calc_MAX_Tracks_To_Format ; Max track count for
  420. ; FormatTrack call
  421. FormatLoop:
  422. call Format_Loop ; Format until CY occurs
  423. cmp Format_End,True ; End of Format?
  424. jne $$IF36
  425. mov FormatError,0 ; signal good format
  426. clc ; clear CY
  427. jmp SHORT $$EN36 ; bad format
  428. $$IF36:
  429. call CheckError ; determine type of error
  430. jc $$IF38
  431. call LastChanceToSaveIt ; acceptable error?
  432. jnc $$IF39 ; yes
  433. mov FormatError,1 ; signal error type
  434. clc ; clear CY
  435. jmp SHORT $$EN39 ; not acceptable error
  436. $$IF39:
  437. call SetStartSector ; start from scratch
  438. call SetfBigFat
  439. push AX
  440. call Phase2Initialization
  441. clc
  442. pop AX
  443. jmp DiskFormat ; try again
  444. $$EN39:
  445. $$IF38:
  446. $$EN36:
  447. return
  448. FormatDone:
  449. mov FormatError,0
  450. clc
  451. return
  452. DiskFormat endp
  453. ;=========================================================================
  454. ; Fat_INIT: This routine initializes the Fat based on the
  455. ; number of paragraphs.
  456. ;
  457. ; input - FatSpace
  458. ; FatSpace+2
  459. ; paras_per_Fat
  460. ; Fat_init_value
  461. ; output - Fat space is initialized
  462. ;
  463. ; Assumes: nothing
  464. ;
  465. ;=========================================================================
  466. Fat_Init PROC NEAR
  467. push ds
  468. push ES
  469. push DI
  470. push AX
  471. push BX
  472. push CX
  473. mov ax,DATA
  474. mov ds,ax
  475. les di,FatSpace
  476. mov BX,Paras_Per_Fat ; Get number of paras
  477. mov AX,Fat_init_value
  478. push DX
  479. mov DX,ES ; Grab ES into DX
  480. $$DO87:
  481. cmp BX,0 ; do while BX not = 0
  482. je $$EN87 ; exit if 0
  483. mov CX,08h ; Word store of paragraph
  484. rep stosw ; Move the data to Fat
  485. xor DI,DI ; Offset always init to 0
  486. inc DX ; Next paragraph
  487. mov ES,DX ; Put next para in ES
  488. dec BX ; Loop iteration counter
  489. jmp SHORT $$DO87
  490. $$EN87:
  491. pop DX
  492. pop CX
  493. pop BX
  494. pop AX
  495. pop DI
  496. pop ES
  497. pop ds
  498. ret
  499. Fat_Init ENDP
  500. ;=========================================================================
  501. ; SetDeviceParameters:
  502. ; Set the device parameters
  503. ;
  504. ; Input:
  505. ; Drive
  506. ; DS:DX - pointer to device parameters
  507. ;=========================================================================
  508. SetDeviceParameters proc near
  509. mov CX, (EXTRAWIO shl 8) or SET_DEVICE_PARAMETERS
  510. cmp IsEXTRAWIODrv,0
  511. jne DoIoctl
  512. mov CX, (RAWIO shl 8) or SET_DEVICE_PARAMETERS
  513. DoIoctl:
  514. mov AX, (IOCTL shl 8) or GENERIC_IOCTL
  515. mov bl, DriveToFormat
  516. inc bl
  517. int 21H
  518. return
  519. SetDeviceParameters endp
  520. ;=========================================================================
  521. ; Prompt_User_For_Disk : This routine prompts the user for the
  522. ; disk to be formatted. An appropriate
  523. ; message is chosen based on the type
  524. ; of switch entered. If the /SELECT
  525. ; switch is entered, the disk prompt is
  526. ; issued through the int 2fh services
  527. ; provided by SELECT.
  528. ;
  529. ; Inputs : SwitchMap - Switches chosen for format
  530. ;
  531. ; Outputs : Message printed as appropriate.
  532. ;=========================================================================
  533. Procedure Prompt_User_For_Disk
  534. push AX
  535. test SwitchMap, (SWITCH_Backup or SWITCH_Select or SWITCH_AUTOTEST)
  536. jnz $$IF186
  537. ifdef NEC_98
  538. test SwitchMap2,SWITCH2_P
  539. jnz $$IF188
  540. endif
  541. call DskPrm ; prompt user for disk
  542. $$IF186:
  543. test SwitchMap, (Switch_Select) ; /SELECT requested?
  544. jz $$IF188
  545. mov AL, DriveToFormat ; get drv to access for format
  546. call AccessDisk ; access the disk
  547. mov AX,Select_Disk_Message ; display disk prompt
  548. int 2fh ; through int 2fh services
  549. $$IF188:
  550. pop AX
  551. ret
  552. Prompt_User_For_Disk ENDP
  553. ;==========================================================================
  554. ; DiskPrompt:
  555. ;
  556. ; This routine prompts for the insertion of the correct diskette
  557. ; into the Target Drive, UNLESS we are being re-entrantly invoked
  558. ; from LastChanceToSaveIt. If the target is a Hardisk we issue a
  559. ; warning message.
  560. ;
  561. ; INPUTS:
  562. ; DeviceParameters.DP_DeviceType
  563. ; fLastChance
  564. ;
  565. ; OUTPUTS:
  566. ; Prompt string
  567. ; fLastChance := FALSE
  568. ;
  569. ; Registers affected:
  570. ; Flags
  571. ;
  572. ;==========================================================================
  573. DskPrm PROC NEAR
  574. cmp fLastChance,TRUE
  575. je PrmptRet
  576. cmp DeviceParameters.DP_DeviceType, DEV_HARDDISK
  577. .errnz EDP_DEVICETYPE NE DP_DEVICETYPE
  578. jne GoPrnIt
  579. ; DblSpaced floppies return DEV_HARDDISK to the GetDeviceParameters
  580. ; call. If this is a DblSpaced drive, go make some additional checks
  581. ; before putting out the hard disk warning.
  582. mov al, DriveToFormat
  583. call IsDblSpaceDisk ; sets Z flag if NOT dblspaced disk
  584. jnz MaybeDblSpace
  585. RealHardDisk:
  586. test DeviceParameters.DP_DeviceAttributes, 1
  587. .errnz EDP_DEVICEATTRIBUTES NE DP_DEVICEATTRIBUTES
  588. jnz non_rem
  589. Message msgDiskWarning
  590. jmp short ask_yes
  591. non_rem:
  592. ifndef OPKBLD
  593. Message msgHardDiskWarning
  594. endif ;OPKBLD
  595. ask_yes:
  596. ifndef OPKBLD
  597. call Yes?
  598. pushf
  599. Message msgCrlf
  600. popf
  601. else
  602. clc
  603. endif ;OPKBLD
  604. jnc OkToFormatHardDisk
  605. mov ExitStatus, EXIT_NO
  606. jmp ExitProgram
  607. OkToFormatHardDisk:
  608. call CrLf
  609. call CrLf
  610. return
  611. ; Got a DblSpaced drive--see if it's removable or not.
  612. MaybeDblSpace:
  613. mov AX, (IOCTL shl 8) or IOCTL_CHANGEABLE?
  614. mov bl, DriveToFormat
  615. inc bl
  616. int 21H
  617. jc RealHardDisk ; should not happen, but if it does...
  618. or ax, ax ; AX=0 if not removable--quietly exit
  619. jnz PrmptRet ; in this case, later checks will
  620. ; stop the format process
  621. GoPrnIt:
  622. mov AL, DriveToFormat
  623. call AccessDisk
  624. Message msgInsertDisk
  625. Message ContinueMsg
  626. call USER_STRING ; Wait for any key
  627. call CrLf
  628. call CrLf
  629. PrmptRet:
  630. mov fLastChance, FALSE
  631. ret
  632. DskPrm ENDP
  633. ;=========================================================================
  634. ; CheckError:
  635. ; Input:
  636. ; AX - extended error code
  637. ; Ouput:
  638. ; carry set if error is Fatal
  639. ; Message printed if Not Ready or Write Protect
  640. ;=========================================================================
  641. CheckError proc near
  642. cmp AX, error_write_protect
  643. je WriteProtectError
  644. cmp AX, error_not_ready
  645. je NotReadyError
  646. cmp CurrentCylinder, 0
  647. jne CheckRealErrors
  648. cmp CurrentHead, 0
  649. je BadTrackZero
  650. CheckRealErrors:
  651. cmp AX, error_CRC
  652. je JustABadTrack
  653. cmp AX, error_sector_not_found
  654. je JustABadTrack
  655. cmp AX, error_write_fault
  656. je JustABadTrack
  657. cmp AX, error_read_fault
  658. je JustABadTrack
  659. cmp AX, error_gen_failure
  660. je JustABadTrack
  661. stc
  662. ret
  663. JustABadTrack:
  664. clc
  665. ret
  666. WriteProtectError:
  667. test SwitchMap,Switch_SELECT ; SELECT option?
  668. jnz $$IF56 ; no - display messages
  669. Message msgCrLf
  670. Message msgCrLf
  671. Extended_Message
  672. jmp SHORT $$EN56 ; yes - set error level
  673. $$IF56:
  674. mov ExitStatus,EXIT_WRIT_PROTECT ; signal write protect error
  675. $$EN56:
  676. stc ; signal Fatal error
  677. ret ; return to caller
  678. NotReadyError:
  679. test SwitchMap,Switch_SELECT ; SELECT option?
  680. jnz $$IF59 ; no - display messages
  681. Message msgCrLf
  682. Message msgCrLf
  683. Extended_Message
  684. jmp SHORT $$EN59 ; yes - set error level
  685. $$IF59:
  686. mov ExitStatus,EXIT_DRV_NOT_READY ;signal Drive not ready
  687. $$EN59:
  688. stc
  689. ret
  690. BadTrackZero:
  691. Message msgDiskUnusable
  692. stc
  693. ret
  694. CheckError endp
  695. ;=========================================================================
  696. ;
  697. ; Calc_MAX_Tracks_To_Format : This routine determines the maximum
  698. ; number of tracks to format at 1 time.
  699. ;
  700. ; Inputs : DeviceParameters - SectorsPerTrack
  701. ; BytesPerSector
  702. ;
  703. ; Outputs : Track_Count - MAX. # of tracks to format in 1 call
  704. ; to FormatTrack
  705. ;=========================================================================
  706. Procedure Calc_Max_Tracks_To_Format
  707. push AX ; Save regs
  708. push BX
  709. push DX
  710. mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
  711. mov BX,DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
  712. .errnz EDP_BPB NE DP_BPB
  713. xor DX,DX
  714. mul BX ; Get total byte count
  715. mov BX,AX ; Put count in BX
  716. mov ax, 1
  717. or dx, dx
  718. jnz cmttf_onetrack
  719. mov AX,MAX_Format_Size ; Max bytes to format
  720. div BX ; Get track count
  721. cmttf_onetrack:
  722. mov Track_Count,AX
  723. pop DX
  724. pop BX
  725. pop AX
  726. ret
  727. Calc_Max_Tracks_To_Format ENDP
  728. ;=========================================================================
  729. ; Format_Loop : This routine provides the main template
  730. ; for the formatting of a disk. A disk
  731. ; will be formatted as long as there are
  732. ; tracks remaining to be formatted.
  733. ; This routine can be exited on a carry
  734. ; condition; i.e., bad track, last track, etc.
  735. ;
  736. ; Inputs : none
  737. ;
  738. ; Outputs : CY - Set on exit from this routine
  739. ; AX - Possible error condition code
  740. ;
  741. ;=========================================================================
  742. Procedure Format_Loop
  743. clc ; Initialize to NC
  744. $$DO173: ; While NC
  745. jc $$EN173 ; Exit on CY
  746. call Calc_Current_Head_Cyl ; Head and cylinder calc.
  747. call Determine_Format_Type ; Floppy/hard media?
  748. call Determine_Track_Count ; How many tracks?
  749. call FormatTrack ; Format track(s)
  750. jnc $$IF175 ; Formattrack failed
  751. pushf ; Save flags
  752. cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ; Harddisk?
  753. .errnz EDP_DEVICETYPE NE DP_DEVICETYPE
  754. jne $$IF176
  755. popf ; Restore flags
  756. call Format_Track_Retry ; Find failing track
  757. jmp SHORT $$EN176
  758. $$IF176:
  759. popf ; Restore flags
  760. $$EN176:
  761. $$IF175:
  762. jnc $$IF180 ; Format error?
  763. pushf ; Yes - save flags
  764. push AX ; Save return code
  765. call CheckRealErrors ; Check error type
  766. jc $$IF181 ; If non-Fatal
  767. call DisplayCurrentTrack ; Display % formatted
  768. $$IF181:
  769. pop AX ; Restore regs
  770. popf
  771. $$IF180:
  772. jc $$EN173 ; Exit on CY
  773. call DisplayCurrentTrack ; Tell how much formatted
  774. call Adj_Track_Count ; Decrease track counter
  775. call NextTrack ; Adjust head and cylinder
  776. jmp SHORT $$DO173
  777. $$EN173:
  778. ret
  779. Format_Loop ENDP
  780. ;=========================================================================
  781. ; Calc_Current_Head_Cyl : Obtain the current head and cylinder of the
  782. ; track being formatted.
  783. ;
  784. ; Inputs: FP_Cylinder - Cylinder of track being formatted
  785. ; FP_Head - Head of track being formatted
  786. ;=========================================================================
  787. Procedure Calc_Current_Head_Cyl
  788. push CX ; save CX
  789. mov CX,FormatPacket.FP_Cylinder ; get current cylinder
  790. mov CurrentCylinder,CX ; put into variable
  791. mov CX,FormatPacket.FP_Head ; get current head
  792. mov CurrentHead,CX ; put into variable
  793. pop CX ; restore CX
  794. ret
  795. Calc_Current_Head_Cyl endp
  796. ; =========================================================================
  797. ; Determine_Format_Type : This routine determines the type of format
  798. ; that is to occur based on the media type.
  799. ;
  800. ; Inputs : Dev_HardDisk - Media type (harddisk)
  801. ; Multi_Track_Format - EQU 02h
  802. ; Single_Track_Format - EQU 00h
  803. ;
  804. ; Outputs : FP_SpecialFunctions - Set appropriately for single
  805. ; or multi track format
  806. ; =========================================================================
  807. Procedure Determine_Format_Type
  808. cmp DeviceParameters.DP_DeviceType,Dev_HardDisk ;harddisk?
  809. .errnz EDP_DEVICETYPE NE DP_DEVICETYPE
  810. jne $$IF158
  811. ; Set for multi track format
  812. mov FormatPacket.FP_SpecialFunctions,Multi_Track_Format
  813. jmp SHORT $$EN158
  814. $$IF158: ; Set for single track format
  815. mov FormatPacket.FP_SpecialFunctions,Single_Track_Format
  816. $$EN158:
  817. ret
  818. Determine_Format_Type ENDP
  819. ;=========================================================================
  820. ;
  821. ; Determine_Track_Count : This routine determines the number of
  822. ; tracks to be formatted, based on whether
  823. ; or not we have a hard disk. If we have
  824. ; a hard disk we can use multi-track
  825. ; format/verify, otherwise we use the
  826. ; single track format/verify.
  827. ;
  828. ; Inputs : Device_Type - Media type
  829. ;
  830. ; Outputs : Tracks_To_Format - MAX. number of tracks
  831. ; to be formatted in one
  832. ; call
  833. ;=========================================================================
  834. Procedure Determine_Track_Count
  835. ; Harddisk?
  836. cmp DeviceParameters.DP_DeviceType,Dev_HardDisk
  837. .errnz EDP_DEVICETYPE NE DP_DEVICETYPE
  838. jne $$IF163
  839. call Calc_Track_Count ; Calc Tracks_To_Format
  840. jmp SHORT $$EN163 ; Removable media
  841. $$IF163:
  842. mov Tracks_To_Format,0001h ; Default to 1 track
  843. $$EN163:
  844. ret
  845. Determine_Track_Count ENDP
  846. ;=========================================================================
  847. ;
  848. ; Calc_Track_Count : This routine determines if we have enough tracks
  849. ; remaining to use the Max. number of tracks
  850. ; in the FormatTrack call. If the tracks remaining
  851. ; to be formatted is less that the mAX. number of
  852. ; allowable tracks for the call, the mAX. number
  853. ; of allowable tracks is set to the remaining track
  854. ; count.
  855. ;
  856. ; Inputs : Track_Count - MAX. number of allowable tracks to be
  857. ; formatted in 1 FormatTrack call.
  858. ; TracksLeft - Track count of remaining tracks to be
  859. ; formatted.
  860. ;
  861. ; Outputs : Tracks_To_Format - Count of the tracks to be formatted
  862. ; in the next FormatTrack call.
  863. ;
  864. ;=========================================================================
  865. Procedure Calc_Track_Count
  866. push AX ; Save regs
  867. mov AX,Track_Count ; Max bytes to format
  868. cmp word ptr TracksLeft+2,0 ; M018; More than 64K of tracks?
  869. jnz $$IF166 ; M018; Then surely use Track_Count
  870. cmp AX,word ptr TracksLeft ; M018; Too many tracks?
  871. JNA $$IF166
  872. mov AX,word ptr TracksLeft ; M018; Format remaining tracks
  873. $$IF166:
  874. mov Tracks_To_Format,AX ; Save track count
  875. pop AX
  876. ret
  877. Calc_Track_Count ENDP
  878. ;=========================================================================
  879. ; FormatTrack : This routine performs multi track or single
  880. ; track formatting based on the state of the
  881. ; SpecialFunctions byte.
  882. ;
  883. ; Inputs : Tracks_To_Format - # of tracks to format in 1 call
  884. ; FormatPacket - Parms for IOCTL call
  885. ;
  886. ; Outputs : NC - formatted track(s)
  887. ; CY - error in format
  888. ; AX - extended error on CY
  889. ;
  890. ;=========================================================================
  891. Procedure FormatTrack
  892. mov AX,(IOCTL shl 8) or Generic_IOCTL
  893. mov BL,DriveToFormat ; Get Drive number
  894. inc BL ; Make it 1 based
  895. mov CX,(RawIO shl 8)
  896. cmp IsEXTRAWIODrv,0
  897. je DoFrmt2
  898. mov CX,(EXTRawIO shl 8)
  899. DoFrmt2:
  900. or CL,Track_Action ; Track_Action is either
  901. ; Format and Verify, or
  902. ; Verify only
  903. mov DX,Tracks_To_Format ; Get track count
  904. mov FormatPacket.FP_TrackCount,DX ; Put count in parms list
  905. lea DX,FormatPacket ; Ptr to parms
  906. int 21h
  907. ;;%out FORQUICK ENABLED!!!!!
  908. ;; clc ;;** ARR
  909. jnc FormatTrackExit ; Error?
  910. mov AH,59h ; Get extended error
  911. xor BX,BX ; Clear BX
  912. int 21h
  913. cmp AX,67 ; Induced error from ENHDISK?
  914. jne notInducedError
  915. clc
  916. ret
  917. notInducedError:
  918. stc ; Flag an error
  919. FormatTrackExit:
  920. ret
  921. FormatTrack ENDP
  922. ;=========================================================================
  923. ;
  924. ; Format_Track_Retry : This routine performs the retry logic for
  925. ; the format multi-track. It will retry each track
  926. ; until the failing track is encountered through
  927. ; a CY condition.
  928. ;
  929. ; Inputs : none
  930. ;
  931. ; Outputs : CY - indicates either a failing track or end of format
  932. ;
  933. ;
  934. ;=========================================================================
  935. Procedure Format_Track_Retry
  936. clc ; Clear existing CY
  937. mov Tracks_To_Format,1 ; Only format 1 track
  938. $$DO168: ; While we have good tracks
  939. jc $$EN168 ; Exit on bad track
  940. call FormatTrack ; Format the track
  941. jc $$IF170 ; Error?
  942. call DisplayCurrentTrack ; Adjust percent counter
  943. call Adj_Track_Count
  944. call NextTrack ; Calc next track
  945. $$IF170:
  946. jmp SHORT $$DO168
  947. $$EN168:
  948. ret
  949. Format_Track_Retry ENDP
  950. ;=========================================================================
  951. ;
  952. ; DisplayCurrentTrack : This procedure prints the percentage of disk
  953. ; formatted so far.
  954. ; If /select is present, format can be exited
  955. ; by returning AX!=0 from the int 2fh call, which
  956. ; is handled by install. This is to permit the
  957. ; user to stop the format in progress.
  958. ;
  959. ;===========================================================================
  960. DisplayCurrentTrack proc near
  961. push DX
  962. push CX
  963. push AX
  964. push DI ; M018
  965. push SI ; M018
  966. mov AX,Tracks_To_Format ;get track count
  967. add Formatted_Tracks_Low,AX ;Indicate formatted a track
  968. adc Formatted_Tracks_High,0
  969. mov AX,Formatted_Tracks_Low
  970. mov BX,Formatted_Tracks_High
  971. mov CX,100 ;Make integer calc for div
  972. call Multiply_32_Bits ; BX:AX = (Cyl * Head *100)
  973. mov DX,BX ;Set up divide
  974. ; DX:AX: 100*head*cylinder (should not be bigger than a DWORD)
  975. ; DI:SI: heads*cylinder
  976. ; We need to assure a word division
  977. mov DI,word ptr TracksPerDisk+2
  978. mov SI,word ptr TracksPerDisk
  979. SetUpDivide:
  980. or DI,DI
  981. jz DivideOK
  982. shr DI,1 ; shift DI:SI 1 bit right
  983. rcr SI,1
  984. shr DX,1 ; shift DX:AX 1 bit right
  985. rcr AX,1
  986. jmp short SetUpDivide
  987. DivideOk:
  988. div SI
  989. cmp AX,PercentComplete ;Only print message when change
  990. je ScreenUpdateDone
  991. ; johnhe 02-27-90
  992. ; Change added here for DOS 5.0 install program to do a
  993. ; special interrupt to display the percent complete on
  994. ; a gage. AX == special code, BX == percent complete
  995. test SwitchMap,Switch_Select ; Was format spawned by the
  996. jz NormalDisplay ; install program?
  997. mov BX,AX ; BX == percent completed
  998. mov AX,GAGE_UPDATE ; AX == special function code
  999. clc
  1000. int 2fh ; Multiplex interrupt
  1001. or AX,AX ; AX <> 0 --> user wants to exit
  1002. jz ScreenUpdateDone
  1003. jmp FatalExit
  1004. ; End of code added for DOS 5.0 install program
  1005. NormalDisplay:
  1006. mov PercentComplete,AX ; Save it if changed
  1007. Message msgCurrentTrack
  1008. ScreenUpdateDone:
  1009. pop SI ; M018
  1010. pop DI ; M018
  1011. pop AX
  1012. pop CX ; Restore register
  1013. pop DX
  1014. return
  1015. DisplayCurrentTrack endp
  1016. ;=========================================================================
  1017. ; Adj_Track_Count : This routine adjusts the track count by the
  1018. ; number of tracks that have been formatted
  1019. ; in one FormatTrack call.
  1020. ;
  1021. ; Inputs : TracksLeft - # of tracks remaining to be formatted
  1022. ; Tracks_To_Format - Tracks formatted in 1 call
  1023. ;
  1024. ; Outputs : TracksLeft - # of tracks remaining to be formatted
  1025. ;=========================================================================
  1026. Procedure Adj_Track_Count
  1027. push AX ; save regs
  1028. push DX ; M018
  1029. mov DX,word ptr TracksLeft+2; get tracks remaining
  1030. mov AX,word ptr TracksLeft
  1031. sub AX,Tracks_To_Format ; subtract amount formatted
  1032. sbb DX,0
  1033. mov word ptr TracksLeft,AX ; save new tracks remaining value
  1034. mov word ptr TracksLeft+2,DX
  1035. pop DX ; M018
  1036. pop AX ; restore regs
  1037. ret
  1038. Adj_Track_Count endp
  1039. ;=========================================================================
  1040. ;
  1041. ; NextTrack : This routine determines the next track to be
  1042. ; formatted.
  1043. ;
  1044. ; Inputs : TracksLeft - # of tracks remaining
  1045. ; Tracks_To_Format - # of tracks to format in 1 call
  1046. ; FP_Head - disk head
  1047. ; FP_Cylinder - disk cylinder
  1048. ;
  1049. ; Outputs : TracksLeft - # of tracks remaining
  1050. ; FP_Head - disk head
  1051. ; FP_Cylinder - disk cylinder
  1052. ; CY - no tracks left to format
  1053. ; NC - tracks left to format
  1054. ;
  1055. ;=========================================================================
  1056. Procedure NextTrack
  1057. mov CX,word ptr TracksLeft+2
  1058. or CX,Word ptr TracksLeft
  1059. jne $$IF149 ; Yes
  1060. stc ; Signal end of format
  1061. mov Format_End,True
  1062. jmp SHORT $$EN149
  1063. $$IF149:
  1064. mov CX,Tracks_To_Format ; Get mAX track count for call
  1065. $$DO151: ; While tracks remain
  1066. cmp CX,00 ; End of head/cyl. adjustment?
  1067. je $$EN151 ; Yes
  1068. inc FormatPacket.FP_Head ; Next head
  1069. mov AX,FormatPacket.FP_Head ; Get head for comp
  1070. cmp AX,DeviceParameters.DP_BPB.oldBPB.BPB_Heads ; Exceeded head count?
  1071. .errnz EDP_BPB NE DP_BPB
  1072. jne $$IF154 ; Yes
  1073. mov FormatPacket.FP_Head,00 ; Reinit. head
  1074. inc FormatPacket.FP_Cylinder ; Next cylinder
  1075. $$IF154:
  1076. dec CX ; Decrease counter
  1077. jmp SHORT $$DO151
  1078. $$EN151:
  1079. clc ; Clear CY
  1080. $$EN149:
  1081. ret
  1082. NextTrack ENDP
  1083. ;=========================================================================
  1084. ; CurrentLogicalSector:
  1085. ; Get the current logical sector number
  1086. ;
  1087. ; Input:
  1088. ; current track = TracksPerDisk - TracksLeft
  1089. ; SectorsPerTrack
  1090. ;
  1091. ; Output:
  1092. ; BX = logical sector number of the first sector in the track we
  1093. ; just tried to format
  1094. ;=========================================================================
  1095. CurrentLogicalSector PROC NEAR
  1096. push AX ; Save regs
  1097. push BX
  1098. push DX
  1099. .386
  1100. mov EAX, TracksPerDisk
  1101. sub EAX, TracksLeft
  1102. movzx ebx, DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
  1103. .errnz EDP_BPB NE DP_BPB
  1104. mul ebx
  1105. mov dword ptr Relative_Sector_Low,EAX ; Save sector #
  1106. .8086
  1107. pop DX ; Restore regs
  1108. pop BX
  1109. pop AX
  1110. return
  1111. CurrentLogicalSector ENDP
  1112. ;=========================================================================
  1113. ;
  1114. ; BadSector:
  1115. ; Reports the bad Sectors.
  1116. ; Reports the track where DiskFormat stopped.
  1117. ; From then on it formats until it reaches a bad track, or end,
  1118. ; and reports that.
  1119. ;
  1120. ; Output:
  1121. ; Carry: set --> Fatal error
  1122. ; if Carry not set
  1123. ; AX - The number of consecutive bad Sectors encountered
  1124. ; AX == 0 --> no More bad Sectors
  1125. ; BX - The logical sector number of the first bad sector
  1126. ;
  1127. ; Algorithm:
  1128. ; if DiskFormatErrors
  1129. ; DiskFormatErrors = false
  1130. ; return current track
  1131. ; else
  1132. ; next track
  1133. ; while not done
  1134. ; if format track fails
  1135. ; return current track
  1136. ; next track
  1137. ; return 0
  1138. ;=========================================================================
  1139. BadSector proc near
  1140. ; Don't bother to do the format
  1141. ; /c was given
  1142. test FormatError, 0ffH
  1143. jz ContinueFormat
  1144. mov FormatError, 0
  1145. jmp SHORT ReportBadTrack
  1146. ContinueFormat:
  1147. call Adj_Track_Count ; Decrease track counter
  1148. call NextTrack ; Adjust head and cylinder
  1149. cmp Format_End,True ; End of format?
  1150. je $$IF44 ; No
  1151. call Format_Loop ; Format until CY
  1152. cmp Format_End,True ; End of format?
  1153. je $$IF45 ; No
  1154. call CheckError ; Must be error - which error?
  1155. jc $$IF46 ; Non-Fatal error?
  1156. call CurrentLogicalSector ; Yes - get position
  1157. ; set tracksize
  1158. mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
  1159. .errnz EDP_BPB NE DP_BPB
  1160. clc ; Signal O.K. to continue
  1161. $$IF46:
  1162. jmp SHORT $$EN45
  1163. $$IF45:
  1164. jmp SHORT NoMoreTracks ;End of format
  1165. $$EN45:
  1166. jmp SHORT $$EN44
  1167. $$IF44:
  1168. jmp SHORT NoMoreTracks ; end of format
  1169. $$EN44:
  1170. return
  1171. ReportBadTrack:
  1172. call CurrentLogicalSector
  1173. mov AX, DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
  1174. clc
  1175. return
  1176. NoMoreTracks: ; Don't display done msg
  1177. test SwitchMap,(Switch_Select or SWITCH_AUTOtest)
  1178. jnz $$IF52 ; if EXEC'd by SELECT
  1179. Message msgFormatComplete
  1180. $$IF52:
  1181. mov AX, 0
  1182. clc
  1183. return
  1184. BadSector endp
  1185. ;=========================================================================
  1186. ; Get_Bad_Sector_Hard : Determine the bad sector.
  1187. ;
  1188. ; Inputs :
  1189. ; Head of failing track
  1190. ; Cylinder of failing track
  1191. ; Relative_Sector_Low - 1st. sector in track
  1192. ; Relative_Sector_High
  1193. ;
  1194. ; ClustBound_Adj_Factor - The number of Sectors
  1195. ; that are to be read
  1196. ; at one time.
  1197. ; ClustBound_SPT_Count - Used by Calc_Cluster_Boundary
  1198. ; to track how many Sectors
  1199. ; have been read.
  1200. ; ClustBound_Flag - True (Use cluster buffer)
  1201. ; - False (Use internal buffer)
  1202. ; ClustBound_Buffer_Seg - Segment of buffer
  1203. ;
  1204. ; Outputs : Marked cluster as bad
  1205. ;=========================================================================
  1206. Procedure Get_Bad_Sector_Hard
  1207. push CX ; Save CX
  1208. mov CX,0001h ; Set counter to start at 1
  1209. mov ClustBound_SPT_Count,00h ; Clear sector counter
  1210. mov ClustBound_Adj_Factor,01h ; Default value
  1211. ; DO WHILE Sectors left
  1212. $$DO115:
  1213. cmp CX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack ;At end?
  1214. .errnz EDP_BPB NE DP_BPB
  1215. ja $$EN115 ; Yes,exit
  1216. push CX ; Save CX
  1217. cmp ClustBound_Flag,True ; Full buffer there?
  1218. jne $$IF117 ; Yes
  1219. call Calc_ClustBound_ ; See if on boundary
  1220. mov AX,ClustBound_Buffer_Seg
  1221. ; Point to transfer area
  1222. mov WORD PTR RWPacket.TRWP_Transferaddress[0],0
  1223. mov WORD PTR RWPacket.TRWP_Transferaddress[2],AX
  1224. jmp SHORT $$EN117 ; Default to internal buffer
  1225. $$IF117: ; Point to transfer area
  1226. mov WORD PTR RWPacket.TRWP_Transferaddress[0],offset RW_TRF_Area
  1227. mov WORD PTR RWPacket.TRWP_Transferaddress[2],DS
  1228. $$EN117:
  1229. call Verify_Structure_Set_Up ; Set up verify vars
  1230. mov AX,(IOCTL shl 8) or GENERIC_IOCTL
  1231. xor BX,BX ; Clear BX
  1232. mov BL,DriveToFormat ; Get Drive
  1233. inc BL ; Adjust it
  1234. mov CX,(IOC_DC shl 8) or READ_TRACK
  1235. cmp IsEXTRAWIODrv,0
  1236. je DoIOCTL2
  1237. mov CX,(IOC_EDC shl 8) or READ_TRACK
  1238. ; Buffer is only cluster size
  1239. DoIOCTL2:
  1240. lea DX,RWPacket ; Point to parms
  1241. int 21h
  1242. pop CX ; Restore CX
  1243. push CX ; Save CX
  1244. jnc $$IF120 ; An error occurred
  1245. call Calc_Cluster_Position ; Determine which cluster
  1246. call BadClus ; Mark the cluster as bad
  1247. $$IF120:
  1248. pop CX
  1249. add CX,ClustBound_Adj_Factor ; Adjust loop counter
  1250. mov AX,ClustBound_Adj_Factor ; Get adjustment factor
  1251. xor DX,DX
  1252. add AX,Relative_Sector_Low ; Add in low word
  1253. adc DX,Relative_Sector_High ; Pick up carry in high word
  1254. mov Relative_Sector_Low,AX ; Save low word
  1255. mov Relative_Sector_High,DX ; Save high word
  1256. jmp SHORT $$DO115
  1257. $$EN115:
  1258. pop CX
  1259. ret
  1260. Get_Bad_Sector_Hard ENDP
  1261. ;=========================================================================
  1262. ; Get_Bad_Sector_Floppy : This routine marks an entire track as bad
  1263. ; since it is a floppy disk.
  1264. ;
  1265. ; Inputs : Relative_Sector_Low - first sector
  1266. ;
  1267. ; Outputs : Fat marked with bad Sectors
  1268. ;=========================================================================
  1269. Procedure Get_Bad_Sector_Floppy
  1270. push BX ; Save regs
  1271. push CX
  1272. ; Get Sectors/track
  1273. mov CX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
  1274. .errnz EDP_BPB NE DP_BPB
  1275. $$DO123: ; While Sectors left
  1276. cmp CX,00 ; At end
  1277. je $$EN123 ; Yes
  1278. push BX ; Save BX we destroy it
  1279. push CX ; Save CX we destroy it
  1280. call Calc_Cluster_Position ; Get cluster position
  1281. call BadClus ; Mark it as bad
  1282. pop CX ; Restore regs
  1283. pop BX
  1284. dec CX ; Decrease loop counter
  1285. .386
  1286. inc dword ptr Relative_Sector_Low ; Next sector
  1287. .8086
  1288. jmp SHORT $$DO123
  1289. $$EN123:
  1290. pop CX ; Restore regs
  1291. pop BX
  1292. ret
  1293. Get_Bad_Sector_Floppy ENDP
  1294. ;=========================================================================
  1295. ;
  1296. ; Inputs: DX:AX - Cluster number
  1297. ; Outputs: The given cluster is marked as invalid
  1298. ; Zero flag is set if the cluster was already marked bad
  1299. ;
  1300. ; Registers modified: DX
  1301. ; SI
  1302. ;
  1303. ; BADCLUS : Marks off a bad cluster in the Fat
  1304. ; If a cluster has already been marked bad it
  1305. ; will return with ZR.
  1306. ;
  1307. ; Inputs : DX:AX - Cluster Number
  1308. ;
  1309. ; Outputs : Cluster is marked invalid
  1310. ; ZR set if cluster already marked bad
  1311. ;
  1312. ;=========================================================================
  1313. BadClus proc near ; mark bad clusters
  1314. push DI ; save affected regs
  1315. push AX
  1316. push BX
  1317. push CX
  1318. push DX
  1319. push ES
  1320. cmp FATNotAllInMem,0
  1321. je DoBadInMem
  1322. push dx ; Save cluster number
  1323. push ax
  1324. call AllocInitBadClusBitmap ; Does nothing if BadClusBitmap
  1325. ; already exists
  1326. .386
  1327. ;; Manual assemble to prevent compile warning
  1328. ;; pop eax ; recover cluster #
  1329. db 066h,058h
  1330. ;;
  1331. jc $$EN10
  1332. push ds
  1333. push si
  1334. lds si,BadClusBitMap
  1335. mov ebx,eax
  1336. shr ebx,19 ; (E)BX is "64k index" of this bit
  1337. and eax,00007FFFFh ; bit index in that 64k
  1338. mov cx,ds
  1339. add cx,bx ; Go to correct 64k piece
  1340. mov ds,cx
  1341. bts dword ptr [si],eax ; Set the bit
  1342. pop si
  1343. pop ds
  1344. jnc short ClrZr
  1345. xor ax,ax ; Set zero flag, cluster already marked
  1346. jmp $$EN10
  1347. ClrZr:
  1348. inc eax ; Clear the zero flag
  1349. .8086
  1350. jmp $$EN10
  1351. DoBadInMem:
  1352. mov ES, WORD PTR FatSpace + 2 ; obtain seg of Fat
  1353. cmp fBig32Fat,TRUE ; 32 bit Fat?
  1354. je $$IF8a ; yes
  1355. cmp fBigFat,TRUE ; 16 bit Fat?
  1356. je $$IF8 ; yes
  1357. ; 12-bit FAT
  1358. mov CX,2 ; divide by 2
  1359. push AX ; saves low cluster number
  1360. mov SI,DX ; pick up high word of cluster
  1361. mov DI,AX ; pick up low word of cluster
  1362. call divide_32_Bits ; 32 bit divide
  1363. add AX,DI ; add in low word of result
  1364. adc DX,SI ; pick up low word carry
  1365. ; cluster = cluster * 1.5
  1366. add AX,WORD PTR FatSpace ; add 0
  1367. adc DX,0 ; pick up carry
  1368. mov BX,DX ; get high word for adjust
  1369. mov CX,ES ; place seg in AX
  1370. call BadClus_address_Adjust ; adjust segment offset
  1371. mov ES,CX ; new segment
  1372. mov SI,AX ; new offset
  1373. mov DX,0ff7h ; bad cluster flag
  1374. mov AX,0fffh ; mask value
  1375. pop CX ; restore AX in CX - low cluster #
  1376. test CX,1 ; is old clus num odd?
  1377. jz $$IF9 ; yes
  1378. .386
  1379. shl AX,4 ; get only 12 bits - fff0
  1380. shl DX,4 ; get 12 bits - ff70
  1381. .8086
  1382. $$IF9:
  1383. jmp SHORT $$EN8
  1384. $$IF8a:
  1385. ; 32-bit FAT
  1386. xor SI,SI ; clear si
  1387. mov BX,DX ; get high word for multiply
  1388. mov CX,4 ; multiply by 4
  1389. call Multiply_32_Bits ; 32 bit multiply due to 4 bytes per
  1390. ; Fat cell. This gives us an offset
  1391. ; into the FAT
  1392. mov CX,ES ; place seg in CX
  1393. call BadClus_Address_Adjust ; adjust segment:offset
  1394. mov ES,CX ; new segment
  1395. mov SI,AX ; new offset
  1396. .386
  1397. mov ecx,dword ptr ES:[SI] ; Get previous value
  1398. and ecx,00FFFFFFFh ; Discard high 4 bits
  1399. mov edx,00ffffff7h
  1400. mov dword ptr ES:[SI],edx ; flag it a bad cluster
  1401. cmp EDX,ECX ; return op == badval;
  1402. .8086
  1403. jmp short $$EN10
  1404. $$IF8:
  1405. ; 16-bit FAT
  1406. xor SI,SI ; clear si
  1407. mov BX,DX ; get high word for multiply
  1408. mov CX,2 ; multiply by 2
  1409. call Multiply_32_Bits ; 32 bit multiply due to 2 bytes per
  1410. ; Fat cell. This gives us an offset
  1411. ; into the FAT
  1412. mov CX,ES ; place seg in CX
  1413. call BadClus_Address_Adjust ; adjust segment:offset
  1414. mov ES,CX ; new segment
  1415. mov SI,AX ; new offset
  1416. mov DX,0fff7h ; bad cluster value
  1417. mov AX,0ffffh ; mask value
  1418. $$EN8:
  1419. mov CX,ES:[SI] ; get contents of Fat cell
  1420. and CX,AX ; make it 12 or 16 bit
  1421. ; depending on value in AX
  1422. not AX ; set AX to 0
  1423. and ES:[SI],AX ; clear Fat entry
  1424. or ES:[SI],DX ; flag it a bad cluster
  1425. cmp DX,CX ; return op == badval;
  1426. $$EN10:
  1427. pop ES
  1428. pop DX
  1429. pop CX
  1430. pop BX
  1431. pop AX
  1432. pop DI
  1433. return
  1434. badclus endp
  1435. ;=========================================================================
  1436. ; Verify_Structure_Set_Up : Set up the fields for the Read IOCTL
  1437. ; to verify the Sectors in a failing
  1438. ; track. Also, it displays the
  1439. ; message notifying the user of the
  1440. ; Sectors it is verifying.
  1441. ;=========================================================================
  1442. Procedure Verify_Structure_Set_Up ; Set up verify structure
  1443. mov RWPacket.TRWP_SpecialFunctions,00h ; Reset special functions
  1444. mov AX,FormatPacket.FP_Head ; Get current head
  1445. mov RWPacket.TRWP_Head,AX ; Get current head
  1446. mov AX,FormatPacket.FP_Cylinder ; Get current cylinder
  1447. mov RWPacket.TRWP_Cylinder,AX ; Get current cylinder
  1448. dec CX ; Make sector 0 based
  1449. mov RWPacket.TRWP_FirstSector,CX ; Get sector to read
  1450. mov AX,ClustBound_Adj_Factor ; Get # of Sectors to read
  1451. mov RWPacket.TRWP_SectorsToReadWrite,AX ; Read only # sector(s)
  1452. call Calc_Cluster_Position ; Determine cluster number
  1453. mov WORD PTR Msg_Allocation_Unit_Val[+2],DX ; Save high word of cluster
  1454. mov WORD PTR Msg_Allocation_Unit_Val[+0],AX ; Save low word of cluster
  1455. message msgVerify
  1456. ret
  1457. Verify_Structure_Set_Up ENDP
  1458. ;=========================================================================
  1459. ; Calc_Cluster_Position : This routine calculates which cluster the
  1460. ; failing sector falls in.
  1461. ;
  1462. ; Inputs : Relative_Sector_High - high word of sector position
  1463. ; Relative_Sector_Low - low word of sector position
  1464. ;
  1465. ; Outputs : DX:AX - Cluster number
  1466. ;=========================================================================
  1467. Procedure Calc_Cluster_Position
  1468. push CX ; Save regs
  1469. push DI
  1470. push SI
  1471. mov DX,WORD PTR Relative_Sector_High ; Get the high sector word
  1472. mov AX,WORD PTR Relative_Sector_Low ; Get the low sector word
  1473. sub AX,word ptr StartSector ; Get relative sector #
  1474. sbb DX,word ptr StartSector+2 ; Pick up borrow
  1475. mov SI,DX ; Get high word
  1476. mov DI,AX ; Get low word
  1477. xor CX,CX ; Clear CX
  1478. ; Get Sectors/cluster
  1479. mov CL,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
  1480. .errnz EDP_BPB NE DP_BPB
  1481. call divide_32_Bits ; 32 bit division
  1482. mov DX,SI ; Get high word of result
  1483. mov AX,DI ; Get low word of result
  1484. add AX,2 ; Adjust for cluster bias
  1485. adc DX,0 ; Pick up carry
  1486. pop SI ; Restore regs
  1487. pop DI
  1488. pop CX
  1489. ret
  1490. Calc_Cluster_Position ENDP
  1491. ;=========================================================================
  1492. ; Calc_ClustBound_ : This routine will determine where, within a
  1493. ; cluster, a sector resides.
  1494. ;
  1495. ; Inputs : Relative_Sector_Low - Sector
  1496. ; Relative_Sector_High
  1497. ;
  1498. ; Outputs : ClustBound_Adj_Factor - The number of Sectors
  1499. ; remaining in the cluster.
  1500. ; ClustBound_SPT_Count - The count of Sectors
  1501. ; having been accessed for
  1502. ; a track.
  1503. ;=========================================================================
  1504. Procedure Calc_ClustBound_
  1505. push AX ; Save regs
  1506. push BX
  1507. push CX
  1508. push DX
  1509. push SI
  1510. push DI
  1511. xor DX,DX ; Clear high word
  1512. mov DX,WORD PTR Relative_Sector_High
  1513. mov AX,WORD PTR Relative_Sector_Low
  1514. sub AX,word ptr StartSector ; Get relative sector #
  1515. sbb DX,word ptr StartSector+2 ; Pick up borrow
  1516. mov SI,DX ; Get high word
  1517. mov DI,AX ; Get low word
  1518. xor CX,CX ; Clear CX
  1519. mov CL,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
  1520. .errnz EDP_BPB NE DP_BPB
  1521. call divide_32_Bits ; 32 bit division
  1522. or CX,CX ; See if remainder exists
  1523. jz $$IF132 ; Remainder exists
  1524. xor BX,BX
  1525. mov BL,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
  1526. sub BX,CX
  1527. mov ClustBound_Adj_Factor,BX ; Remainder = sector count
  1528. jmp SHORT $$EN132 ; Noremainder
  1529. $$IF132:
  1530. xor BX,BX ; Clear BX
  1531. mov BL,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster
  1532. mov ClustBound_Adj_Factor,BX
  1533. $$EN132:
  1534. mov AX,ClustBound_SPT_Count ; Get current sector count
  1535. xor DX,DX ; Clear high word
  1536. add AX,ClustBound_Adj_Factor ; Get next sector count
  1537. ; Exceeded Sectors/track?
  1538. cmp AX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
  1539. jna $$IF135 ; Yes
  1540. ; only use difference
  1541. mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerTrack
  1542. sub AX,ClustBound_SPT_Count ; Get next sector count
  1543. mov ClustBound_Adj_Factor,AX
  1544. $$IF135:
  1545. mov AX,ClustBound_SPT_Count ; Get sector count
  1546. xor DX,DX ; Clear high word
  1547. add AX,ClustBound_Adj_Factor ; Get new sector count
  1548. mov ClustBound_SPT_Count,AX ; Save it
  1549. pop DI ; Restore regs
  1550. pop SI
  1551. pop DX
  1552. pop CX
  1553. pop BX
  1554. pop AX
  1555. ret
  1556. Calc_ClustBound_ ENDP
  1557. ;=========================================================================
  1558. ;
  1559. ; BadClus_address_Adjust - This routine adjusts the segment and
  1560. ; offset to provide addressibility into
  1561. ; the Fat table.
  1562. ;
  1563. ; Inputs : BX - high word to adjust segment for
  1564. ; AX - low word to adjust segment for
  1565. ; CX - segment to be adjusted
  1566. ;
  1567. ; Outputs : CX - new segment value
  1568. ; AX - new offset value
  1569. ;
  1570. ;=========================================================================
  1571. Procedure BadClus_address_Adjust
  1572. push BX ; Save regs
  1573. push DX
  1574. push DI
  1575. push SI
  1576. mov DX,CX ; Save segment value
  1577. mov SI,BX ; Get high word for divide
  1578. mov DI,AX ; Get low word for divide
  1579. xor CX,CX ; Clear CX
  1580. mov CL,Paragraph_Size ; Divide by 16
  1581. call divide_32_Bits ; Perform division
  1582. add DX,DI ; Adjust segment for result
  1583. mov AX,CX ; Pick up the remainder
  1584. mov CX,DX ; Pass back new segment
  1585. pop SI ; Restore regs
  1586. pop DI
  1587. pop DX
  1588. pop BX
  1589. ret
  1590. BadClus_address_Adjust ENDP
  1591. ;=========================================================================
  1592. ;Routine name: Multiply_32_Bits
  1593. ;=========================================================================
  1594. ;Description: A real sleazy 32 bit x 16 bit multiply routine. Works by adding
  1595. ; the 32 bit number to itself for each power of 2 contained in the
  1596. ; 16 bit number. Whenever a bit that is set in the multiplier (CX)
  1597. ; gets shifted to the bit 0 spot, it means that that amount has
  1598. ; been multiplied so far, and it should be added into the total
  1599. ; value. Take the example CX = 12 (1100). Using the associative
  1600. ; rule, this is the same as CX = 8+4 (1000 + 0100). The
  1601. ; multiply is done on this principle - whenever a bit that is set
  1602. ; is shifted down to the bit 0 location, the value in BX:AX is
  1603. ; added to the running total in DI:SI. The multiply is continued
  1604. ; until CX = 0. The routine will exit with CY set if overflow
  1605. ; occurs.
  1606. ;
  1607. ;
  1608. ;Called Procedures: None
  1609. ;
  1610. ;Change History: Created 7/23/87 MT
  1611. ;
  1612. ;Input: BX:AX = 32 bit number to be multiplied
  1613. ; CX = 16 bit number to be multiplied. (Must be even number)
  1614. ;
  1615. ;Output: BX:AX = output.
  1616. ; CY set if overflow
  1617. ;
  1618. ;=========================================================================
  1619. Multiply_32_Bits PROC
  1620. .386
  1621. push ax
  1622. mov ax,bx
  1623. shl eax,16
  1624. pop ax
  1625. movzx ecx,cx
  1626. mul ecx
  1627. mov ebx,eax
  1628. shr ebx,16
  1629. or edx,edx ; Overflow?
  1630. jz short OkRet ; No, carry clear
  1631. stc
  1632. OkRet:
  1633. .8086
  1634. ret
  1635. Multiply_32_Bits endp
  1636. ;=========================================================================
  1637. ; divide_32_Bits - This routine will perform 32bit division
  1638. ; It works by first dividing the high word
  1639. ; and leaving the remainder in DX and then
  1640. ; dividing the low word with the remainder
  1641. ; still in DX
  1642. ;
  1643. ; Inputs : SI:DI - value to be divided
  1644. ; CX - divisor
  1645. ;
  1646. ; Outputs : SI:DI - result
  1647. ; CX - remainder
  1648. ;=========================================================================
  1649. Procedure divide_32_Bits
  1650. push AX ; Save regs
  1651. push BX
  1652. push DX
  1653. xor DX,DX ; clear DX
  1654. mov AX,SI ; get high word
  1655. div CX ; get high word result
  1656. mov SI,AX ; save high word result
  1657. mov AX,DI ; get low word
  1658. div CX ; get low word result
  1659. mov DI,AX ; save low word result
  1660. mov CX,DX ; pick up remainder
  1661. pop DX ; restore regs
  1662. pop BX
  1663. pop AX
  1664. ret
  1665. divide_32_Bits endp
  1666. ;=========================================================================
  1667. ;
  1668. ; QuickFormat : This procedure will perform a Quick format by
  1669. ; simply copying any bad cluster markers from the
  1670. ; old FAT on the disk to the new FAT. The old FAT is
  1671. ; read in one sector at a time using FatSector buffer.
  1672. ; The new FAT is held in FatSpace buffer.
  1673. ;
  1674. ; Registers Destroyed : SI,AX,BX,CX
  1675. ;
  1676. ; Assumes: DS:DATA,ES:Nothing
  1677. ;
  1678. ;=========================================================================
  1679. QuickFormat proc near
  1680. mov SI,DATA
  1681. mov ES,SI ; Set ES to data segment
  1682. assume ES:DATA,DS:Nothing ; Assembler directive
  1683. ; Set device parameters here
  1684. mov ES:DeviceParameters.DP_SpecialFunctions,(INSTALL_FAKE_BPB or TRACKLAYOUT_IS_GOOD)
  1685. .errnz EDP_SPECIALFUNCTIONS NE DP_SPECIALFUNCTIONS
  1686. lea DX,ES:DeviceParameters
  1687. call SetDeviceParameters
  1688. .386
  1689. mov ES:sector_in_buffer,0ffffffffh ; force first read to ensure
  1690. ; buffer validity
  1691. test ES:fBig32FAT,0ffh ; See if 32 bit fat
  1692. jz short Test16BitEntry ; If zero then 16 or 12 bit fat
  1693. mov EBX,00ffffff7h ; Set 32 bit value for bad cluster
  1694. jmp SHORT InitClusCount
  1695. Test16BitEntry:
  1696. test ES:fBigFAT,0ffh ; See if 16 bit fat
  1697. jz short Set12BitEntry ; If zero then 12 bit fat
  1698. mov EBX,0000fff7h ; Set 16 bit value for bad cluster
  1699. jmp SHORT InitClusCount
  1700. Set12BitEntry:
  1701. mov EBX,00000ff7h ; Set 12 bit value for bad cluster
  1702. InitClusCount:
  1703. mov ES:CurrentCluster,2 ; M015; No need to do the first 2
  1704. mov ES:BadClusValue,EBX
  1705. cmp es:FATNotAllInMem,0
  1706. je short QuickLoop
  1707. push ds
  1708. push es
  1709. pop ds
  1710. message msgSetBadClus
  1711. pop ds
  1712. QuickLoop:
  1713. mov EAX,ES:CurrentCluster
  1714. call calc_sector_and_offset ; determine location of this entry
  1715. mov EBX,ES:sector_in_buffer
  1716. mov EAX,ES:sector_to_read
  1717. cmp EAX,EBX ; check if required sector is in buffer
  1718. je short DontHaveToRead
  1719. cmp es:FATNotAllInMem,0
  1720. je short DoRead
  1721. push ds
  1722. push es
  1723. pop ds
  1724. call DisplayFatDonePcnt
  1725. pop ds
  1726. DoRead:
  1727. call ReadFatSector ; read a sector of the FAT into buffer
  1728. jc ExitQuickFormatCRLFErr ; check for error
  1729. DontHaveToRead:
  1730. mov EAX,ES:CurrentCluster ; EAX = current cluster
  1731. xor CX,CX ; ECX = get cluster contents signal
  1732. lds SI,ES:FatSector ; DS:SI --> FAT buffer
  1733. call GetFatSectorEntry ; EAX = contents of FAT entry
  1734. mov EBX,ES:BadClusValue ; Restore bad cluster value
  1735. cmp EAX,EBX ; Is this cluster marked bad?
  1736. jne short NextCluster ; If EAX<>EBX good cluster
  1737. MarkInFormatBuffer:
  1738. cmp es:FATNotAllInMem,0
  1739. je short DoBadInMem2
  1740. push es
  1741. pop ds
  1742. call AllocInitBadClusBitmap ; Does nothing if BadClusBitmap
  1743. ; already exists
  1744. jc short ExitQuickFormatCRLFErr ; check for error
  1745. mov EAX,ES:CurrentCluster ; EAX = current cluster
  1746. lds si,es:BadClusBitMap
  1747. mov ebx,eax
  1748. shr ebx,19 ; (E)BX is "64k index" of this bit
  1749. and eax,00007FFFFh ; bit index in that 64k
  1750. mov cx,ds
  1751. add cx,bx ; Go to correct 64k piece
  1752. mov ds,cx
  1753. bts dword ptr [si],eax ; Set the bit
  1754. jmp short NextCluster
  1755. DoBadInMem2:
  1756. mov ECX,EBX ; ECX = value to set in FAT buffer
  1757. mov EAX,ES:CurrentCluster ; EAX = this cluster number
  1758. lds SI,ES:FatSpace ; DS:SI --> Format's FAT buffer
  1759. call GetSetFatEntry ; Set the cluster in Format's buffer
  1760. NextCluster:
  1761. inc ES:CurrentCluster ; go to next cluster
  1762. mov EAX,ES:CurrentCluster
  1763. mov EBX,ES:TotalClusters
  1764. cmp EAX,EBX ; check for last cluster in FAT
  1765. jna QuickLoop
  1766. .8086
  1767. mov BX,DATA
  1768. mov DS,BX ; restore DS to DATA segment
  1769. assume DS:DATA,ES:DATA ; Assembler directive
  1770. cmp ds:FATNotAllInMem,0
  1771. je ExitQuickFormatRet ; Carry clear if jmp
  1772. message msgSetBadClusDone
  1773. clc
  1774. ExitQuickFormatRet:
  1775. ret
  1776. ExitQuickFormatCRLFErr:
  1777. mov BX,DATA
  1778. mov DS,BX
  1779. cmp ds:FATNotAllInMem,0
  1780. stc
  1781. je ExitQuickFormatRet
  1782. Message msgCrLf
  1783. stc
  1784. jmp short ExitQuickFormatRet
  1785. QuickFormat endp
  1786. ;===========================================================================
  1787. ;
  1788. ; calc_sector_and_offset : This procedure computes the logical sector
  1789. ; number the given FAT entry is in, and its
  1790. ; offset from the start of the sector.
  1791. ;
  1792. ; Inputs : EAX = entry number
  1793. ; fBigFat = flag for 12- or 16-bit FAT entries
  1794. ; Number of reserved sectors
  1795. ;
  1796. ; Output : sector_to_read = logical disk sector holding FAT entry
  1797. ; entry_offset = offset from start of sector
  1798. ; odd_entry = flag for 12-bit entry alignment (1=odd,0=even)
  1799. ;
  1800. ; Registers Destroyed : AX,BX,CX,DX
  1801. ;
  1802. ; Strategy : This procedure assumes the sector size is 512 bytes.
  1803. ; The byte offset from the start of the FAT is first
  1804. ; calculated. This is then divided by 512, so that
  1805. ; required sector = quotient
  1806. ; offset = remainder
  1807. ; The logical sector number is obtained by adding on the
  1808. ; number of reserved sectors.
  1809. ;
  1810. ; M017: The code does not assume 512 BytesPerSector (it is even simpler!)
  1811. ;============================================================================
  1812. calc_sector_and_offset proc near
  1813. assume DS:NOTHING,ES:DATA
  1814. .386
  1815. xor EDX,EDX
  1816. test ES:fBig32Fat,0ffh ; See if 32 bit FAT
  1817. jz short TestOffset16 ; If not do 16 or 12 bit FAT
  1818. shl EAX,1 ; EAX *= 2
  1819. rcl EDX,1
  1820. jmp short FindOffset16 ; Now mult by 2 again for * 4
  1821. TestOffset16:
  1822. test ES:fBigFat,0ffh ; See if 16 bit FAT
  1823. jz short FindOffset12 ; If not do 12 bit FAT
  1824. FindOffset16:
  1825. shl EAX,1 ; EAX *= 2
  1826. rcl EDX,1
  1827. ; Now offset from start of FAT is
  1828. ; in EDX:EAX
  1829. jmp SHORT FindSector
  1830. FindOffset12:
  1831. mov BX,AX ; BX = cluster number
  1832. shl AX,1
  1833. add AX,BX ; AX *= 3
  1834. mov ES:odd_entry,AL ; lsb of AX determines even or odd
  1835. and ES:odd_entry,1
  1836. shr AX,1 ; Divide by 2
  1837. ; Now offset from start of FAT is
  1838. ; in EDX:EAX
  1839. FindSector:
  1840. movzx ebx,ES:DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
  1841. .errnz EDP_BPB NE DP_BPB
  1842. div ebx
  1843. mov ES:entry_offset,DX
  1844. movzx ebx,ES:DeviceParameters.DP_BPB.oldBPB.BPB_RESERVEDSECTORS
  1845. add EAX,ebx
  1846. mov ES:sector_to_read,EAX
  1847. .8086
  1848. ret
  1849. calc_sector_and_offset endp
  1850. ;===========================================================================
  1851. ;
  1852. ; ReadFatSector : This procedure will read in a sector of the FAT
  1853. ; into the FatSector buffer. This is done by loading
  1854. ; the required parameters and calling ReadWriteSectors.
  1855. ;
  1856. ; Input : sector_to_read
  1857. ; Output: loaded buffer
  1858. ; sector_in_buffer
  1859. ;
  1860. ; Registers destroyed: AX,BX,CX,DX
  1861. ;
  1862. ;===========================================================================
  1863. ReadFatSector proc near
  1864. assume DS:NOTHING,ES:DATA
  1865. push DS ; Preserve DS
  1866. .386
  1867. mov EDX,ES:sector_to_read ; EDX = starting sector
  1868. ;; Manual assemble to prevent compile warning
  1869. ;; push edx
  1870. db 066h,052h
  1871. ;;
  1872. cmp ES:DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFAT,0
  1873. .errnz EDP_BPB NE DP_BPB
  1874. je short NotBigFAT1
  1875. mov cx,ES:DeviceParameters.DP_BPB.BGBPB_ExtFlags
  1876. test cx,BGBPB_F_NoFATMirror
  1877. jz short NotBigFAT1
  1878. and ecx,NOT BGBPB_F_ActiveFATMsk
  1879. jz short NotBigFAT1
  1880. mov ebx,edx
  1881. mov eax,dword ptr ES:DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
  1882. mul ecx
  1883. add eax,ebx
  1884. mov edx,eax
  1885. NotBigFAT1:
  1886. mov ebx,edx
  1887. shr ebx,16
  1888. mov ES:Read_Write_Relative.Start_Sector_High,bx
  1889. mov AL,ES:DriveToFormat ; AL = DOS drive number
  1890. mov CX,1 ; 1 sector only
  1891. lds BX,ES:FatSector ; DS:BX --> read buffer
  1892. call Read_Disk ; perform read
  1893. ;; Manual assemble to prevent compile warning
  1894. ;; pop edx
  1895. db 066h,05Ah
  1896. ;;
  1897. mov ES:sector_in_buffer,EDX ; update sector in memory
  1898. .8086
  1899. pop DS ; Restore DS
  1900. ret
  1901. ReadFatSector endp
  1902. ;=========================================================================
  1903. ; WriteFatSector : This routine writes the logical sector count requested.
  1904. ; of the FAT
  1905. ;
  1906. ; Inputs : AL - Drive letter
  1907. ; DS:BX - Segment:offset of transfer address
  1908. ; ECX - Sector count
  1909. ; EDX - 1st. sector
  1910. ; ES -> Data
  1911. ;
  1912. ; Outputs : Logical Sectors written
  1913. ;=========================================================================
  1914. procedure WriteFatSector
  1915. assume DS:NOTHING,ES:DATA
  1916. .386
  1917. $$DO67:
  1918. or ECX,ECX ; any Sectors?
  1919. jz short $$EN67 ; no
  1920. ifdef NEC_98
  1921. cmp ECX,10h ; Single write?
  1922. jna short $$IF69 ; yes
  1923. ;; Manual assemble to prevent compilke warning
  1924. ;; push ECX ; save count left
  1925. db 066h,051h
  1926. ;;
  1927. mov CX,10h
  1928. push AX ; save AX
  1929. mov eax,edx
  1930. shr eax,16
  1931. mov Read_Write_Relative.Start_Sector_High,ax
  1932. pop ax ; Recover drive
  1933. push ax
  1934. ;; Manual assemble to prevent compile warning
  1935. ;; push EDX
  1936. db 066h,052h
  1937. ;;
  1938. call write_disk ; write it
  1939. ;; Manual assemble to prevent compile warning
  1940. ;; pop EDX
  1941. db 066h,05Ah
  1942. ;;
  1943. pop AX ; restore AX
  1944. ;; Manual assemble to prevent compile warning
  1945. ;; pop ECX ; restore count
  1946. db 066h,059h
  1947. ;;
  1948. jc short Write_Exit ; exit if fail
  1949. mov SI,ES:DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
  1950. shl SI,1
  1951. shl SI,1
  1952. shl SI,1
  1953. shl SI,1 ; * 10h
  1954. call seg_adj ; adjust segment
  1955. mov BX,SI ; new offset
  1956. add EDX,10h
  1957. sub ECX,10h
  1958. jmp SHORT $$DO67
  1959. else
  1960. cmp ECX,40h ; Single write?
  1961. jna short $$IF69 ; yes
  1962. ;; Manual assemble to prevent compilke warning
  1963. ;; push ECX ; save count left
  1964. db 066h,051h
  1965. ;;
  1966. mov CX,40h
  1967. push AX ; save AX
  1968. mov eax,edx
  1969. shr eax,16
  1970. mov Read_Write_Relative.Start_Sector_High,ax
  1971. pop ax ; Recover drive
  1972. push ax
  1973. ;; Manual assemble to prevent compile warning
  1974. ;; push EDX
  1975. db 066h,052h
  1976. ;;
  1977. call write_disk ; write it
  1978. ;; Manual assemble to prevent compile warning
  1979. ;; pop EDX
  1980. db 066h,05Ah
  1981. ;;
  1982. pop AX ; restore AX
  1983. ;; Manual assemble to prevent compile warning
  1984. ;; pop ECX ; restore count
  1985. db 066h,059h
  1986. ;;
  1987. jc short Write_Exit ; exit if fail
  1988. mov SI,8000h
  1989. call seg_adj ; adjust segment
  1990. mov BX,SI ; new offset
  1991. add EDX,40h
  1992. sub ECX,40h
  1993. jmp SHORT $$DO67
  1994. endif
  1995. $$IF69:
  1996. push AX ; save drive
  1997. mov eax,edx
  1998. shr eax,16
  1999. mov Read_Write_Relative.Start_Sector_High,ax
  2000. pop ax ; Recover drive
  2001. push ax
  2002. call write_disk ; write it
  2003. pop AX ; restore AX
  2004. mov ECX,0 ; set CX to 0 - last read
  2005. .8086 ; DO NOT XOR!!!
  2006. $$EN67:
  2007. Write_Exit:
  2008. ret
  2009. WriteFatSector ENDP
  2010. FlushCurrInMemFATBuf proc near
  2011. ASSUME DS:DATA,ES:NOTHING
  2012. push ds
  2013. push ds
  2014. pop es
  2015. .386
  2016. assume ES:DATA
  2017. movzx cx,DeviceParameters.DP_BPB.oldBPB.BPB_NumberOfFats ;loop control
  2018. .errnz EDP_BPB NE DP_BPB
  2019. or CX,CX ;check for zero
  2020. stc
  2021. jz short FFMExit
  2022. movzx eax,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
  2023. or ax,ax
  2024. jnz short GtFatSz
  2025. mov eax,dword ptr DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
  2026. GtFatSz:
  2027. mov edx,CurrFATInMemStartSec
  2028. lds BX,FatSpace ;DS:BX --> FatSpace
  2029. assume DS:NOTHING,ES:DATA
  2030. mov SI,BX ;Set up for add. calc
  2031. call SEG_ADJ ;Get adjusted seg:off
  2032. mov BX,SI ;Get new offset
  2033. WriteFatLp: ;loop while FATs > 0
  2034. ;; Manual assemble to prevent compile warning
  2035. ;; push eax ;Save FAT size
  2036. db 066h,050h
  2037. ;;
  2038. push BX ;save Fat offset
  2039. push DS ;save Fat segment
  2040. push CX ;save Fat count
  2041. ;; Manual assemble to prevent compile warning
  2042. ;; push EDX ;Fat start sector
  2043. db 066h,052h
  2044. ;;
  2045. mov ecx,CurrFATInMemSecCnt
  2046. mov AL,DriveToFormat
  2047. call WriteFatSector ;write the Fat
  2048. ;; Manual assemble to prevent compile warning
  2049. ;; pop EDX ;get 1st. Fat sector
  2050. db 066h,05Ah
  2051. ;;
  2052. pop CX ;get Fat count
  2053. pop DS ;restore Fat segment
  2054. pop BX ;restore Fat offset
  2055. ;; Manual assemble to prevent compile warning
  2056. ;; pop eax ;restore FAT size
  2057. db 066h,058h
  2058. ;;
  2059. jc short FFMExit ;check for errors
  2060. add EDX,EAX ;next FAT start sector
  2061. loop WriteFatLp ;write all FATs
  2062. clc
  2063. FFMExit:
  2064. pop ds
  2065. ret
  2066. FlushCurrInMemFATBuf endp
  2067. DisplayFatDonePcnt proc near
  2068. assume DS:DATA,ES:NOTHING
  2069. .386
  2070. mov eax,CurrentCluster
  2071. dec eax
  2072. dec eax
  2073. mov ecx,100
  2074. mul ecx
  2075. mov ecx,TotalClusters
  2076. dec ecx
  2077. dec ecx
  2078. div ecx
  2079. .8086
  2080. cmp ax,100
  2081. jbe PcntOk
  2082. mov ax,100
  2083. PcntOk:
  2084. cmp AX,PercentComplete ;Only print message when change
  2085. je NoUpd
  2086. mov PercentComplete,AX ; Save it if changed
  2087. Message msgCurrentTrack
  2088. NoUpd:
  2089. ret
  2090. DisplayFatDonePcnt endp
  2091. ;===========================================================================
  2092. ; Routine name: FlushFATBuf
  2093. ;===========================================================================
  2094. ;
  2095. ; Description: Flush the in memory FAT buffer out to the disk
  2096. ;
  2097. ; Arguments: None
  2098. ; ----------------------------------------------------------------
  2099. ; Returns: carry set if error
  2100. ; -----------------------------------------------------
  2101. ; Registers destroyed: EAX EBX ECX EDX
  2102. ; ----------------------------------------
  2103. ; Strategy
  2104. ; --------
  2105. ;===========================================================================
  2106. FlushFATBuf PROC near
  2107. assume DS:DATA,ES:NOTHING
  2108. push DS ;preserve DS
  2109. cmp FATNotAllInMem,0
  2110. .386
  2111. je WrtWholeFat
  2112. ;
  2113. ; What we have at this point is the first part of the FAT in the in
  2114. ; memory FAT buf and the BadClusBitMap which indicates what clusters
  2115. ; we want to mark bad.
  2116. ;
  2117. ; Go through the in memory FAT buf (currently first FATSecCntInMem
  2118. ; sectors of the FAT) marking any bad clusters, and/or write an EOF
  2119. ; mark in the root directory start cluster, write it out.
  2120. ;
  2121. ; For rest of FAT, zero init in memory FAT buf, mark bad clusters
  2122. ; and/or put EOF mark in root directory start cluster and write it out.
  2123. ;
  2124. ; We had better be talking 32-bit FAT here!!!!!! 12-bit and 16-bit
  2125. ; FATs always fit in memory.
  2126. ;
  2127. test fBig32FAT,0ffh
  2128. stc ; Set error
  2129. jz ExitWriteFat ; Not 32-bit FAT !!!?????
  2130. ; Set the bad clus value
  2131. mov BadClusValue,00ffffff7h ; Set 32 bit value for bad cluster
  2132. ; Set the current in mem FAT start sector
  2133. movzx eax,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors
  2134. .errnz EDP_BPB NE DP_BPB
  2135. mov CurrFATInMemStartSec,eax
  2136. ; Calculate how many clusters fit in memory NOTE that since we are
  2137. ; restricted to 32-bit FAT here we KNOW clusters do not span sector
  2138. ; boundaries in the FAT.
  2139. mov eax,FATSecCntInMem
  2140. mov CurrFATInMemSecCnt,eax
  2141. movzx ecx,DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
  2142. mul ecx
  2143. mov ecx,4 ; 4 bytes per cluster
  2144. div ecx
  2145. mov FATInMemClusCnt,eax
  2146. ; Init the in memory buffer with the start of the fat
  2147. call init_fat_with_header
  2148. message msgWriteFat
  2149. ; Set the rest of the buffer control variables for the in memory buffer
  2150. mov CurrentCluster,2
  2151. mov CurrFATInMemStartClus,0
  2152. ClusLoop2:
  2153. call DisplayFatDonePcnt
  2154. mov eax,dword ptr DeviceParameters.DP_BPB.BGBPB_RootDirStrtClus
  2155. cmp eax,2
  2156. jb short NoRootEOF
  2157. cmp EAX,TotalClusters
  2158. ja short NoRootEOF
  2159. sub eax,CurrFATInMemStartClus
  2160. jc short NoRootEOF
  2161. cmp eax,FATInMemClusCnt
  2162. jae short NoRootEOF
  2163. shl eax,2 ; * 4 bytes per cluster
  2164. mov ecx,00FFFFFFFh
  2165. push ds
  2166. lds BX,FatSpace ;DS:BX --> FatSpace
  2167. assume DS:nothing
  2168. ror eax,16 ; AX is high 16 bits of EAX
  2169. ; which is "64k index" of
  2170. ; this DWORD
  2171. shl ax,12 ; Convert to SEGMENT value
  2172. push cx ; Save low 16 of bad mark
  2173. mov cx,ds
  2174. add cx,ax
  2175. mov ds,cx
  2176. pop cx
  2177. ror eax,16 ; Get back offset in this 64k
  2178. add bx,ax ; Index this cluster entry
  2179. mov dword ptr ds:[bx],ecx ; Mark as BAD
  2180. pop ds
  2181. assume DS:data
  2182. NoRootEOF:
  2183. cmp BadClusBitMap,0 ; Anything to mark?
  2184. je short NoBadToMark ; Nope
  2185. mov eax,CurrentCluster
  2186. push ds
  2187. lds si,BadClusBitMap
  2188. assume DS:nothing
  2189. mov ebx,eax
  2190. shr ebx,19 ; (E)BX is "64k index" of this bit
  2191. and eax,00007FFFFh ; bit index in that 64k
  2192. mov cx,ds
  2193. add cx,bx ; Go to correct 64k piece
  2194. mov ds,cx
  2195. bt dword ptr [si],eax ; Bad cluster?
  2196. pop ds
  2197. assume DS:data
  2198. jnc short NxtClus ; No
  2199. mov eax,CurrentCluster
  2200. sub eax,CurrFATInMemStartClus
  2201. shl eax,2 ; * 4 bytes per cluster
  2202. mov ecx,BadClusValue
  2203. push ds
  2204. lds BX,FatSpace ;DS:BX --> FatSpace
  2205. assume DS:nothing
  2206. ror eax,16 ; AX is high 16 bits of EAX
  2207. ; which is "64k index" of
  2208. ; this DWORD
  2209. shl ax,12 ; Convert to SEGMENT value
  2210. push cx ; Save low 16 of bad mark
  2211. mov cx,ds
  2212. add cx,ax
  2213. mov ds,cx
  2214. pop cx
  2215. ror eax,16 ; Get back offset in this 64k
  2216. add bx,ax ; Index this cluster entry
  2217. mov dword ptr ds:[bx],ecx ; Mark as BAD
  2218. pop ds
  2219. assume DS:data
  2220. NxtClus:
  2221. inc CurrentCluster
  2222. mov eax,CurrentCluster
  2223. sub eax,CurrFATInMemStartClus
  2224. cmp eax,FATInMemClusCnt
  2225. jae short NextBuf
  2226. jmp short TestDone
  2227. NoBadToMark:
  2228. mov eax,FATInMemClusCnt
  2229. cmp CurrentCluster,2 ; Special case?
  2230. ja short OkayAdd ; No
  2231. sub eax,2 ; Special case for first FAT buffer
  2232. OkayAdd:
  2233. add CurrentCluster,eax
  2234. NextBuf:
  2235. call FlushCurrInMemFATBuf
  2236. jc short ExitWriteFatCRLFErr
  2237. call Fat_Init ; Zero init the in mem buffer
  2238. mov eax,CurrFATInMemSecCnt
  2239. add eax,CurrFATInMemStartSec
  2240. movzx ECX,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors
  2241. movzx edx,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
  2242. or dx,dx
  2243. jnz short GtFatSz2
  2244. mov edx,dword ptr DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
  2245. GtFatSz2:
  2246. add ecx,edx ; First sector after the FAT
  2247. cmp eax,ecx ; Start sector in the FAT area?
  2248. jae short DoMsgDone ; No, all done, carry clear if jump
  2249. mov CurrFATInMemStartSec,eax
  2250. sub ecx,eax ; ecx is count of sectors left in FAT
  2251. cmp ecx,CurrFATInMemSecCnt ; Partial buffer at end of FAT?
  2252. jae short CntOK ; No.
  2253. mov CurrFATInMemSecCnt,ecx ; Last part of FAT < buffer size
  2254. CntOK:
  2255. mov eax,CurrentCluster
  2256. mov CurrFATInMemStartClus,eax
  2257. TestDone:
  2258. mov EAX,CurrentCluster
  2259. cmp EAX,TotalClusters ; check for last cluster in FAT
  2260. jna ClusLoop2
  2261. .8086
  2262. call FlushCurrInMemFATBuf ; Sets carry for return
  2263. jc ExitWriteFatCRLFErr
  2264. DoMsgDone:
  2265. message msgSetBadClusDone
  2266. clc
  2267. jmp short ExitWriteFat
  2268. ExitWriteFatCRLFErr:
  2269. Message msgCrLf
  2270. stc
  2271. jmp short ExitWriteFat
  2272. WrtWholeFat:
  2273. .386
  2274. push ds
  2275. pop es
  2276. assume ES:DATA
  2277. movzx cx,DeviceParameters.DP_BPB.oldBPB.BPB_NumberOfFats ;loop control
  2278. or CX,CX ;check for zero
  2279. jz short ExitWriteFat
  2280. movzx eax,ES:DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
  2281. or ax,ax
  2282. jnz short GotFatSz
  2283. mov eax,dword ptr ES:DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
  2284. GotFatSz:
  2285. movzx EDX,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors ;starting sector
  2286. lds BX,FatSpace ;DS:BX --> FatSpace
  2287. assume DS:NOTHING,ES:DATA
  2288. mov SI,BX ;Set up for add. calc
  2289. call SEG_ADJ ;Get adjusted seg:off
  2290. mov BX,SI ;Get new offset
  2291. WriteFatLoop: ;loop while FATs > 0
  2292. ;; Manual assemble to prevent compile warning
  2293. ;; push eax ;Save FAT size
  2294. db 066h,050h
  2295. ;;
  2296. push BX ;save Fat offset
  2297. push DS ;save Fat segment
  2298. push CX ;save Fat count
  2299. ;; Manual assemble to prevent compile warning
  2300. ;; push EDX ;Fat start sector
  2301. db 066h,052h
  2302. ;;
  2303. mov ecx,eax
  2304. mov AL,DriveToFormat
  2305. call WriteFatSector ;write the Fat
  2306. ;; Manual assemble to prevent compile warning
  2307. ;; pop EDX ;get 1st. Fat sector
  2308. db 066h,05Ah
  2309. ;;
  2310. pop CX ;get Fat count
  2311. pop DS ;restore Fat segment
  2312. pop BX ;restore Fat offset
  2313. ;; Manual assemble to prevent compile warning
  2314. ;; pop eax ;restore FAT size
  2315. db 066h,058h
  2316. ;;
  2317. jc short ExitWriteFat ;check for errors
  2318. add EDX,EAX ;next FAT start sector
  2319. loop WriteFatLoop ;write all FATs
  2320. ExitWriteFatOK:
  2321. clc ;signal success
  2322. ExitWriteFat:
  2323. pop DS ;restore DS
  2324. assume DS:DATA
  2325. ret
  2326. FlushFATBuf endp
  2327. ;===========================================================================
  2328. ; Routine name: GetSetFatEntry
  2329. ;===========================================================================
  2330. ;
  2331. ; Description: Returns or sets the contents of the specified fat
  2332. ; entry from a specified buffer. The buffer may be
  2333. ; up to 128K in length for 16 bit FATs and 16K for
  2334. ; 12 bit FATs.
  2335. ;
  2336. ; WARNING: Do not call this if FATNotAllInMem is TRUE
  2337. ;
  2338. ; Arguments: DS:SI --> Start of FAT buffer
  2339. ; EAX = Cluster number
  2340. ; ECX = 0fffffffeh if get cluster else set cluster from ECX
  2341. ; ----------------------------------------------------------------
  2342. ; Returns: EAX --> Contents of FAT entry
  2343. ; -----------------------------------------------------
  2344. ; Registers destroyed: EAX EBX ECX EDX
  2345. ; ----------------------------------------
  2346. ; Strategy
  2347. ; --------
  2348. ;===========================================================================
  2349. GetSetFatEntry PROC near
  2350. assume DS:NOTHING,ES:DATA
  2351. push SI ; Save regs for 'C' compatibility
  2352. push DS
  2353. push ES
  2354. ; mov BX,DATA ; ES = DATA
  2355. ; mov ES,BX
  2356. call Seg_Adj ; Normalize the pointer
  2357. .386
  2358. xor edx,edx
  2359. test ES:fBig32Fat,0ffh ; See if 32 bit FAT
  2360. jz short TestEntry16 ; If not do 12 bit FAT
  2361. shl EAX,1 ; EDX:EAX *= 2
  2362. rcl edx,1
  2363. jmp short FindEntry16 ; and *2 again for total of *4
  2364. TestEntry16:
  2365. test ES:fBigFat,0ffh ; See if 16 bit FAT
  2366. jz short FindEntry12 ; If not do 12 bit FAT
  2367. FindEntry16:
  2368. shl EAX,1 ; EDX:EAX *= 2
  2369. rcl edx,1
  2370. AddToBufStart: ; Offset in EAX may be > 64K
  2371. mov EBX,16 ; Convert EDX:EAX to paragraphs
  2372. div EBX ; (AX = DX:AX / 16) (DX = DX:AX % 16)
  2373. mov BX,DS ; Add paragraphs to DS
  2374. add AX,BX
  2375. mov DS,AX
  2376. add SI,DX ; Add remaining offset in DX to SI
  2377. cmp ecx,0fffffffeh ; if ECX == 0fffffffeh, then get entry
  2378. jz short GetFatEntry16
  2379. test ES:fBig32Fat,0ffh ; See if 32 bit FAT
  2380. jz short DoEntry16a
  2381. mov dword ptr [SI],ECX ; Set the entry
  2382. jmp SHORT GetSetEntryExit
  2383. DoEntry16a:
  2384. mov word ptr [SI],CX ; Set the entry
  2385. jmp SHORT GetSetEntryExitzx ; AX = FAT entry
  2386. GetFatEntry16:
  2387. test ES:fBig32Fat,0ffh ; See if 32 bit FAT
  2388. jz short DoEntry16
  2389. mov EAX,dword ptr [SI] ; Move the entry into EAX
  2390. and EAX,00FFFFFFFh ; Discard high 4 bits
  2391. jmp SHORT GetSetEntryExit ; EAX = FAT entry
  2392. .8086
  2393. DoEntry16:
  2394. mov AX,word ptr [SI] ; Move the entry into AX
  2395. jmp SHORT GetSetEntryExitzx ; AX = FAT entry
  2396. FindEntry12:
  2397. mov BX,AX ; BX = cluster number
  2398. shl AX,1
  2399. add AX,BX ; AX *= 3
  2400. test AX,1 ; Test lsb of AX to see if even or odd
  2401. pushf ; Save zero flag
  2402. shr AX,1 ; Divid by 2
  2403. add SI,AX ; Address the cluster
  2404. mov AX,[SI] ; AX = entry + part of another entry
  2405. popf ; Get bit test off the stack
  2406. jnz OddCluster ; If not zero then it's an odd cluster
  2407. EvenCluster:
  2408. cmp cx,0fffeh
  2409. jz GetEvenCluster ; Check for get or set
  2410. and AX,0f000h ; Zero out the value in 12 lsb
  2411. or AX,CX ; Set the new value
  2412. mov [SI],AX
  2413. jmp SHORT GetSetEntryExitzx ; AX = FAT entry
  2414. GetEvenCluster:
  2415. and AX,0fffh ; Mask off high 4 bits
  2416. jmp SHORT GetSetEntryExitzx ; AX = FAT entry
  2417. OddCluster:
  2418. cmp cx,0fffeh
  2419. jz GetOddCluster ; Check for get or set
  2420. .386
  2421. shl CX,4 ; Set the value Shift left 4 bits
  2422. .8086
  2423. and AX,0fh ; Zero out existing value in 12 msb
  2424. or AX,CX ; Insert new value
  2425. mov [SI],AX
  2426. jmp SHORT GetSetEntryExitzx ; AX = FAT entry
  2427. GetOddCluster:
  2428. .386
  2429. shr AX,4 ; Shift over 4 bits to get entry
  2430. GetSetEntryExitzx:
  2431. movzx eax,ax
  2432. .8086
  2433. GetSetEntryExit:
  2434. pop ES ; Restore regs for 'C' compatibility
  2435. pop DS
  2436. pop SI
  2437. ret
  2438. GetSetFatEntry ENDP
  2439. ;===========================================================================
  2440. ; Routine name: GetFatSectorEntry
  2441. ;===========================================================================
  2442. ;
  2443. ; Description: Returns the contents of the specified fat
  2444. ; entry from the FatSector buffer. It is assumed that the
  2445. ; required sector is in the buffer already. If the entry is
  2446. ; 12 bits and overlaps sectors, the next sector will be read
  2447. ; into the FatSector buffer.
  2448. ;
  2449. ; Arguments: DS:SI --> Start of FatSector buffer
  2450. ; entry_offset = offset of entry from start of buffer
  2451. ; fBigFat fBig32Fat = flags for 12-16-32-bit FAT
  2452. ; -------------------------------------------------------------------------
  2453. ; Returns: EAX --> Contents of FAT entry
  2454. ; -----------------------------------------------------
  2455. ; Registers destroyed: EAX BX CX DX
  2456. ; ---------------------------------
  2457. ;
  2458. ;===========================================================================
  2459. GetFatSectorEntry PROC near
  2460. assume DS:NOTHING,ES:DATA
  2461. push SI ; Save regs for 'C' compatibility
  2462. push DS
  2463. push ES
  2464. ; mov BX,DATA ; ES = DATA
  2465. ; mov ES,BX
  2466. call Seg_Adj ; Normalize the pointer
  2467. mov DX,ES:entry_offset
  2468. add SI,DX ; Add offset value in DX to SI
  2469. test ES:fBig32Fat,0ffh ; See if 32 bit FAT
  2470. jz short TestEntry16x ; If not do 12-16 bit FAT
  2471. .386
  2472. mov EAX,dword ptr [SI] ; Move the entry into AX
  2473. and EAX,00FFFFFFFh ; Discard high 4 bits
  2474. .8086
  2475. jmp SHORT GetFatSectorEntryExit ; EAX = FAT entry
  2476. TestEntry16x:
  2477. test ES:fBigFat,0ffh ; See if 16 bit FAT
  2478. jz Get12 ; If not do 12 bit FAT
  2479. Get16:
  2480. .386
  2481. movzx EAX,word ptr [SI] ; Move the entry into AX
  2482. .8086
  2483. jmp SHORT GetFatSectorEntryExit ; EAX = FAT entry
  2484. Get12:
  2485. ifdef NEC_98
  2486. ;;; mov AX,DeviceParameters.DP_BPB.BPB_BytesPerSector
  2487. ; Fix for B#7418
  2488. mov AX,ES:DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector
  2489. dec AX
  2490. cmp DX,AX
  2491. else
  2492. cmp DX,1ffh ; Entry straddles two FAT sectors if
  2493. endif
  2494. jb Does_Not_Straddle ; offset is 511 (last byte in sector)
  2495. Does_Straddle:
  2496. call ReadInTwoParts ; Handle special case by reading in
  2497. jmp SHORT GetFatSectorEntryExit ; the next FAT sector also
  2498. Does_Not_Straddle:
  2499. .386
  2500. movzx EAX,word ptr [SI] ; EAX = entry + part of another entry
  2501. .8086
  2502. test ES:odd_entry,1
  2503. jnz IsOddCluster ; If not zero then it's an odd cluster
  2504. IsEvenCluster:
  2505. and AX,0fffh ; Mask off high 4 bits
  2506. jmp SHORT GetFatSectorEntryExit ; EAX = FAT entry
  2507. IsOddCluster:
  2508. .386
  2509. shr AX,4 ; Shift over 4 bits to get entry
  2510. .8086
  2511. GetFatSectorEntryExit:
  2512. pop ES ; Restore regs for 'C' compatibility
  2513. pop DS
  2514. pop SI
  2515. ret
  2516. GetFatSectorEntry ENDP
  2517. ;===========================================================================
  2518. ;
  2519. ; ReadInTwoParts : This procedure will determine the value of a 12-bit
  2520. ; FAT entry which is straddled across two consecutive
  2521. ; sectors in the FAT. The value is found by reading
  2522. ; the available part from the first sector, and then
  2523. ; loading the next sector in the FatSector buffer and
  2524. ; reading and combining the next part.
  2525. ; Input : odd_entry
  2526. ; sector_to_read
  2527. ; DS:SI pointer to required entry location in buffer (this is
  2528. ; offset 511 from start of FatSector buffer)
  2529. ;
  2530. ; Output: AX = entry value
  2531. ; FatSector contains next FAT sector
  2532. ;
  2533. ; Registers destroyed : AX
  2534. ;
  2535. ; Strategy : The position of the entry is different for odd and even
  2536. ; entries. The 3-byte layout for two consecutive 12-bit entries
  2537. ; is shown below. (The byte |X1 X0| or |Y2 X2| is the last
  2538. ; in the buffer).
  2539. ;
  2540. ; |X1 X0|Y0 X2|Y2 Y1|
  2541. ;
  2542. ; Even entries start at X1 (thus need to get X2X1X0).
  2543. ; Odd entries start at Y0 (thus need to get Y2Y1Y0).
  2544. ;
  2545. ;===========================================================================
  2546. ReadInTwoParts proc near
  2547. assume DS:NOTHING,ES:DATA
  2548. push BX ; Save registers
  2549. push CX
  2550. push DX
  2551. push SI
  2552. xor AX,AX
  2553. mov AL,BYTE PTR [SI] ; read last byte of buffer
  2554. .386
  2555. mov EBX,ES:sector_to_read ; compute next sector to read
  2556. inc EBX
  2557. mov ES:sector_to_read,EBX
  2558. .8086
  2559. test ES:odd_entry,1
  2560. jnz OddEntry
  2561. EvenEntry:
  2562. push AX
  2563. call ReadFatSector ; read in the next FAT sector
  2564. pop AX
  2565. lds SI,ES:FatSector ; set DS:SI to start of buffer
  2566. xor BX,BX
  2567. mov BH,BYTE PTR [SI] ; read first byte of buffer
  2568. and BH,0fh ; mask out Y2
  2569. or AX,BX ; place X2 into position
  2570. jmp SHORT EndReadInTwo
  2571. OddEntry:
  2572. and AL,0f0h ; mask out X2
  2573. mov CL,4
  2574. shr AX,CL ; place Y0 into position
  2575. push AX
  2576. call ReadFatSector ; read in the next FAT sector
  2577. pop AX
  2578. lds SI,ES:FatSector ; set DS:SI to start of buffer
  2579. xor BX,BX
  2580. mov BL,BYTE PTR [SI] ; read first byte of buffer
  2581. mov CL,4
  2582. shl BX,CL
  2583. or AX,BX ; place Y2 Y1 into position
  2584. EndReadInTwo:
  2585. pop SI ; Restore registers
  2586. pop DX
  2587. pop CX
  2588. pop BX
  2589. ret
  2590. ReadInTwoParts endp
  2591. AllocInitBadClusBitmap proc near
  2592. assume DS:DATA,ES:NOTHING
  2593. push es
  2594. .386
  2595. cmp BadClusBitMap,0
  2596. jne short DoneOk
  2597. mov ebx, TotalClusters
  2598. add ebx,32 ; 32 not 31
  2599. shr ebx,5 ; Cnt of DWORDs
  2600. shl ebx,2 ; Cnt of BYTEs
  2601. add ebx,15
  2602. shr ebx,4 ; Cnt of paras
  2603. %out BUG limit on bad cluster bitmap
  2604. cmp ebx,00005000h ; Bitmap > 320k? (2,621,440 clusters)
  2605. ja short ErrExit_Alloc_BCB ; Yes
  2606. mov AH, Alloc
  2607. int 21h
  2608. jc short Exit_Alloc_BCB
  2609. mov WORD PTR BadClusBitMap+2,AX
  2610. mov es,ax
  2611. xor di,di
  2612. xor AX,AX
  2613. mov WORD PTR BadClusBitMap,AX
  2614. movzx ecx,bx ; Cnt of paras
  2615. shl ecx,3 ; 8 words per para
  2616. mov edx,ecx
  2617. NxtBlock:
  2618. cmp ecx,8000h ; More than 64k left?
  2619. jbe short ZotIt ; Nope, last one
  2620. mov ecx,00008000h ; Do at most 64k at a time
  2621. ZotIt:
  2622. mov ebx,ecx ; Save count
  2623. cld
  2624. rep stosw ; zero init bit array
  2625. sub edx,ebx ; Sub off amount done
  2626. jbe short DoneOk ; All done
  2627. mov ax,es
  2628. add ax,1000h ; Next 64k
  2629. mov es,ax
  2630. xor di,di
  2631. mov ecx,edx
  2632. jmp short NxtBlock
  2633. .8086
  2634. DoneOk:
  2635. clc
  2636. Exit_Alloc_BCB:
  2637. pop es
  2638. ret
  2639. ErrExit_Alloc_BCB:
  2640. stc
  2641. jmp short Exit_Alloc_BCB
  2642. AllocInitBadClusBitmap endp
  2643. ;*** SetUpBadClusTransfer - Set things up to copy bad clusters from the current
  2644. ; disk to the new disk.
  2645. ;
  2646. ; DS -> data
  2647. ;
  2648. SetUpBadClusTransfer proc near
  2649. assume DS:DATA,ES:NOTHING
  2650. mov word ptr BadClusBitMap,0
  2651. mov word ptr BadClusBitMap+2,0
  2652. cmp FATNotAllInMem,0
  2653. .386
  2654. je InitFatWithBad
  2655. call DetermineExistingFormatNoMsg
  2656. cmc
  2657. jnc AllDone6 ; Drive isn't valid so no bad sectors
  2658. ;
  2659. ; Build a bit map of the bad clusters
  2660. ;
  2661. message msgSetBadClus
  2662. .386
  2663. test fBig32FAT,0ffh ; See if 32 bit fat
  2664. jz short Tst16BitEntry ; If zero then 16 or 12 bit fat
  2665. mov EBX,00ffffff7h ; Set 32 bit value for bad cluster
  2666. jmp SHORT SetBdVal
  2667. Tst16BitEntry:
  2668. mov EBX,00000ff7h ; Set 12 bit value for bad cluster
  2669. test fBigFAT,0ffh ; See if 16 bit fat
  2670. jz short SetBdVal ; If zero then 12 bit fat
  2671. mov EBX,0000fff7h ; Set 16 bit value for bad cluster
  2672. SetBdVal:
  2673. mov CurrentCluster,2
  2674. mov BadClusValue,EBX
  2675. push ds
  2676. pop es ; following routines expect ES->DATA
  2677. ClusLoop:
  2678. call DisplayFatDonePcnt
  2679. mov EAX,CurrentCluster
  2680. call calc_sector_and_offset ; determine location of this entry
  2681. mov EBX,sector_in_buffer
  2682. mov EAX,sector_to_read
  2683. cmp EAX,EBX ; check if required sector is in buffer
  2684. je short DontHaveToRead2
  2685. call ReadFatSector ; read a sector of the FAT into buffer
  2686. jc short AllDoneDoCRLFErr
  2687. DontHaveToRead2:
  2688. mov EAX,CurrentCluster ; EAX = current cluster
  2689. xor CX,CX ; ECX = get cluster contents signal
  2690. push ds
  2691. lds SI,FatSector ; DS:SI --> FAT buffer
  2692. call GetFatSectorEntry ; EAX = contents of FAT entry
  2693. pop ds
  2694. cmp EAX,BadClusValue ; Is this cluster marked bad?
  2695. jne short NextClus ; If EAX<>EBX good cluster
  2696. call AllocInitBadClusBitmap ; Does nothing if BadClusBitMap
  2697. jc short AllDoneDoCRLFErr ; already exists
  2698. mov EAX,CurrentCluster ; EAX = this cluster number
  2699. push ds
  2700. lds si,BadClusBitMap
  2701. mov ebx,eax
  2702. shr ebx,19 ; (E)BX is "64k index" of this bit
  2703. and eax,00007FFFFh ; bit index in that 64k
  2704. mov cx,ds
  2705. add cx,bx ; Go to correct 64k piece
  2706. mov ds,cx
  2707. bts dword ptr [si],eax ; Set the bit
  2708. pop ds
  2709. NextClus:
  2710. inc CurrentCluster ; go to next cluster
  2711. mov EAX,CurrentCluster
  2712. mov EBX,TotalClusters
  2713. cmp EAX,EBX ; check for last cluster in FAT
  2714. .8086
  2715. jna ClusLoop
  2716. message msgSetBadClusDone
  2717. jmp short AllDone6Ok
  2718. AllDoneDoCRLFErr:
  2719. message msgCRLF
  2720. stc
  2721. jmp short AllDone6
  2722. InitFatWithBad:
  2723. call load_old_fat ; load old FAT
  2724. call mark_non_bad_as_free ; mark anything not BAD as FREE
  2725. AllDone6Ok:
  2726. clc
  2727. AllDone6:
  2728. ret
  2729. SetUpBadClusTransfer endp
  2730. ;*** mark_non_bad_as_free -- mark all non-bad blocks as free in the FAT
  2731. ;
  2732. ; WARNING: Do not call this if FATNotAllInMem is TRUE
  2733. ;
  2734. mark_non_bad_as_free proc near
  2735. assume ds:nothing, es:DATA
  2736. .386
  2737. test fBig32FAT,0ffh ; See if 32 bit fat
  2738. mov ebx,00ffffff7h ; get bad value for 32-bit
  2739. jnz short mark_non_bad_1
  2740. test fBigFAT,0ffh ; See if 16 bit fat
  2741. mov ebx,0fff7h ; get bad value for 16-bit
  2742. jnz short mark_non_bad_1
  2743. and bh,0fh ; get the 0ff7h for 12-bit
  2744. mark_non_bad_1:
  2745. mov eax,2 ; cluster number
  2746. mark_non_bad_2:
  2747. push ds
  2748. lds si,FatSpace ; point to the FAT buffer
  2749. mov ecx,0fffffffeh ; get the FAT entry
  2750. ;; Manual to disable compile warning
  2751. ;; push eax ; save cluster number
  2752. db 066h,050h
  2753. ;; push ebx ; save bad value
  2754. db 066h,053h
  2755. call GetSetFatEntry ; read the cluster value
  2756. ;; pop ebx
  2757. db 066h,05Bh
  2758. cmp eax,ebx ; is it bad?
  2759. jz short mark_non_bad_3 ; skip if so (leave alone)
  2760. ;; pop eax ; get the cluster number
  2761. db 066h,058h
  2762. ;; push eax
  2763. db 066h,050h
  2764. ;; push ebx
  2765. db 066h,053h
  2766. xor ecx,ecx ; set FAT entry to FREE
  2767. call GetSetFatEntry
  2768. ;; pop ebx
  2769. db 066h,05Bh
  2770. mark_non_bad_3:
  2771. ;; pop eax ; restore cluster number
  2772. db 066h,058h
  2773. pop ds
  2774. inc eax
  2775. cmp eax,TotalClusters
  2776. jna mark_non_bad_2
  2777. .8086
  2778. ret
  2779. mark_non_bad_as_free endp
  2780. ;*** load_old_fat -- loads the FAT from the existing media into FatSpace
  2781. ;
  2782. ; WARNING: Do not call this if FATNotAllInMem is TRUE
  2783. ;
  2784. ; If not properly formatted, will just terminate.
  2785. ; If any error reading FAT, will zero entire FAT via Fat_Init.
  2786. load_old_fat proc near
  2787. mov SI,DATA
  2788. mov ES,SI ; Set ES to data segment
  2789. assume ES:DATA,DS:Nothing ; Assembler directive
  2790. push ds
  2791. call DetermineExistingFormatNoMsg
  2792. jc load_old_fat_error
  2793. call init_fat_with_header
  2794. mov CX, DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat
  2795. .errnz EDP_BPB NE DP_BPB
  2796. or cx, cx
  2797. jnz short GotFSz
  2798. ;
  2799. ; We KNOW the high word must be 0 since whole FAT fits in memory
  2800. ;
  2801. mov cx, DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat
  2802. GotFSz:
  2803. mov DX,DeviceParameters.DP_BPB.oldBPB.BPB_ReservedSectors ;starting sector
  2804. mov AL,DriveToFormat
  2805. lds bx,FatSpace
  2806. load_old_fat_1:
  2807. jcxz load_old_fat_done ; exit when done
  2808. ifdef NEC_98
  2809. push cx ; save size to write
  2810. cmp cx,10h ; need more than 40h secs?
  2811. jb load_old_fat_2 ; skip if we can get it all
  2812. mov cx,10h ; clip to max
  2813. load_old_fat_2:
  2814. push AX ; save AX
  2815. call Read_Disk ; read it
  2816. pop AX ; restore AX
  2817. pop CX ; restore CX
  2818. jc load_old_fat_error ; exit if error
  2819. push ax
  2820. mov ax,ds
  2821. add ax,es:DeviceParameters.DP_BPB.BPB_BytesPerSector; adjust segment
  2822. mov ds,ax
  2823. pop ax
  2824. add DX,10h
  2825. sub CX,10h
  2826. ja load_old_fat_1 ; loop until done
  2827. else
  2828. push cx ; save size to write
  2829. cmp cx,40h ; need more than 40h secs?
  2830. jb load_old_fat_2 ; skip if we can get it all
  2831. mov cx,40h ; clip to max
  2832. load_old_fat_2:
  2833. push AX ; save AX
  2834. call Read_Disk ; read it
  2835. pop AX ; restore AX
  2836. pop CX ; restore CX
  2837. jc load_old_fat_error ; exit if error
  2838. push ax
  2839. mov ax,ds
  2840. add ax,40h*512/16 ; adjust segment
  2841. mov ds,ax
  2842. pop ax
  2843. add DX,40h
  2844. sub CX,40h
  2845. ja load_old_fat_1 ; loop until done
  2846. endif
  2847. load_old_fat_done:
  2848. pop ds
  2849. jmp short init_fat_header
  2850. load_old_fat_error:
  2851. pop ds
  2852. if2
  2853. .errnz (offset $) - (offset init_fat_with_header) ; fall thru!
  2854. endif
  2855. load_old_fat endp
  2856. ;*** init_fat_with_header -- Do a Fat_Init, and then put bytes at front
  2857. ;
  2858. ; alternate entry point: init_fat_header (just fill in header)
  2859. init_fat_with_header proc near
  2860. assume ds:nothing, es:DATA
  2861. mov DI,DATA
  2862. mov ES,DI
  2863. call Fat_Init
  2864. init_fat_header:
  2865. push ES
  2866. push es
  2867. pop ds ; get ds -> DATA
  2868. assume ds:DATA
  2869. les DI, FatSpace ; ES:DI --> FatSpace buffer
  2870. assume es:nothing ; Store media descriptor byte
  2871. mov AL, DeviceParameters.DP_BPB.oldBPB.BPB_MediaDescriptor
  2872. .errnz EDP_BPB NE DP_BPB
  2873. ifdef NEC_98
  2874. cmp AL,Fixed_Disk ;FAT-ID twisted (for HD and 5"MO)
  2875. jne @F ; F8h --> FEh (Only FAT-ID)
  2876. mov AL,Single_8_Media ;it is NEC_98 local.
  2877. @@:
  2878. endif
  2879. mov AH, 0ffH
  2880. stosw ; Cluster 0 start
  2881. mov al,ah
  2882. stosb ; cluster 0 if 32 bit else cluster 1
  2883. test fBig32Fat, TRUE
  2884. jz Not32
  2885. stosb ; finish cluster 0 dword
  2886. stosw ; cluster 1 dword
  2887. and ah,0Fh ; High nibble reserved, zero it.
  2888. stosw
  2889. sub di,5 ; Go back to high byte of cluster 0
  2890. mov al,ah
  2891. stosb ; High nibble reserved, zero it.
  2892. jmp short NotBig
  2893. Not32:
  2894. test fBigFat, TRUE
  2895. jz NotBig
  2896. stosb ; finish cluster 1 word
  2897. NotBig:
  2898. pop ES
  2899. ret
  2900. init_fat_with_header endp
  2901. ;**** IsThisClusterBad
  2902. ;
  2903. ; ENTRY: EAX is cluster #
  2904. ;
  2905. ; EXIT: Zero set if cluster bad
  2906. ;
  2907. ; USES: EBX,ECX,EDX,FLAGS
  2908. ;
  2909. IsThisClusterBad proc near
  2910. assume ds:data, es:data
  2911. push ds
  2912. push si
  2913. .386
  2914. ;; push eax
  2915. db 066h,050h
  2916. cmp FATNotAllInMem,0
  2917. je short ChkInMemFat
  2918. cmp BadClusBitMap,0 ; Anything marked?
  2919. je short NotBadRet ; Nope
  2920. lds si,BadClusBitMap
  2921. assume DS:nothing
  2922. mov ebx,eax
  2923. shr ebx,19 ; (E)BX is "64k index" of this bit
  2924. and eax,00007FFFFh ; bit index in that 64k
  2925. mov cx,ds
  2926. add cx,bx ; Go to correct 64k piece
  2927. mov ds,cx
  2928. bt dword ptr [si],eax ; Bad cluster?
  2929. jnc short NotBadRet ; No
  2930. mov bx,0FFFFh ; Set so following inc sets ZERO
  2931. NotBadRet:
  2932. inc bx
  2933. PopRet:
  2934. ;; pop eax ; restore cluster number
  2935. db 066h,058h
  2936. .8086
  2937. pop si
  2938. pop ds
  2939. ret
  2940. ChkInMemFat:
  2941. .386
  2942. assume DS:data
  2943. test fBig32FAT,0ffh
  2944. jz short Tst16BitEnt
  2945. mov EBX,00ffffff7h
  2946. jmp SHORT SetBVal
  2947. Tst16BitEnt:
  2948. mov EBX,00000ff7h
  2949. test fBigFAT,0ffh
  2950. jz short SetBVal
  2951. mov EBX,0000fff7h
  2952. SetBVal:
  2953. mov BadClusValue,EBX
  2954. mov ECX,0fffffffeh ; ECX = Get value
  2955. lds SI,FatSpace
  2956. assume DS:nothing
  2957. call GetSetFatEntry
  2958. cmp eax,es:BadClusValue
  2959. .8086
  2960. jmp short PopRet
  2961. IsThisClusterBad endp
  2962. ;**** WrtEOFMrkInRootClus
  2963. ;
  2964. ; ENTRY: None
  2965. ;
  2966. ; EXIT: EOF mark written into root directory staring cluster
  2967. ;
  2968. ; USES: EAX,EBX,ECX,EDX,FLAGS
  2969. ;
  2970. WrtEOFMrkInRootClus proc near
  2971. assume ds:data, es:data
  2972. push ds
  2973. push si
  2974. ;
  2975. ; In FATNotAllInMem case FlushFatBuf will take care of putting
  2976. ; an eof mark in the root clus
  2977. ;
  2978. cmp FATNotAllInMem,0
  2979. jne SetDone
  2980. test fBig32FAT,0ffh ; See if 32 bit fat
  2981. jz SetDone ; No
  2982. .386
  2983. mov eax,dword ptr DeviceParameters.DP_BPB.BGBPB_RootDirStrtClus
  2984. .errnz EDP_BPB NE DP_BPB
  2985. cmp eax,2
  2986. jb short SetDone
  2987. cmp eax,TotalClusters
  2988. ja short SetDone
  2989. mov ECX,00fffffffh
  2990. .8086
  2991. lds SI,FatSpace
  2992. assume DS:nothing
  2993. call GetSetFatEntry
  2994. SetDone:
  2995. pop si
  2996. pop ds
  2997. ret
  2998. WrtEOFMrkInRootClus endp
  2999. CODE ENDS
  3000. END