diff options
| author | 2024-04-25 21:24:10 +0100 | |
|---|---|---|
| committer | 2024-04-25 22:32:27 +0000 | |
| commit | 2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch) | |
| tree | 80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/DOS/FAT.ASM | |
| parent | Merge pull request #430 from jpbaltazar/typoptbr (diff) | |
| download | ms-dos-main.tar.gz ms-dos-main.tar.xz ms-dos-main.zip | |
Diffstat (limited to '')
| -rw-r--r-- | v4.0/src/DOS/FAT.ASM | 695 |
1 files changed, 695 insertions, 0 deletions
diff --git a/v4.0/src/DOS/FAT.ASM b/v4.0/src/DOS/FAT.ASM new file mode 100644 index 0000000..971c427 --- /dev/null +++ b/v4.0/src/DOS/FAT.ASM | |||
| @@ -0,0 +1,695 @@ | |||
| 1 | ; SCCSID = @(#)fat.asm 1.3 85/08/15 | ||
| 2 | ; SCCSID = @(#)fat.asm 1.3 85/08/15 | ||
| 3 | TITLE FAT - FAT maintenance routines | ||
| 4 | NAME FAT | ||
| 5 | ; Low level local device routines for performing disk change sequence, | ||
| 6 | ; setting cluster validity, and manipulating the FAT | ||
| 7 | ; | ||
| 8 | ; IsEof | ||
| 9 | ; UNPACK | ||
| 10 | ; PACK | ||
| 11 | ; MAPCLUSTER | ||
| 12 | ; FATREAD_SFT | ||
| 13 | ; FATREAD_CDS | ||
| 14 | ; FAT_operation | ||
| 15 | ; | ||
| 16 | ; Revision history: | ||
| 17 | ; | ||
| 18 | ; AN000 version Jan. 1988 | ||
| 19 | ; A001 PTM -- disk changed for look ahead buffers | ||
| 20 | ; | ||
| 21 | |||
| 22 | ; | ||
| 23 | ; get the appropriate segment definitions | ||
| 24 | ; | ||
| 25 | .xlist | ||
| 26 | include dosseg.asm | ||
| 27 | |||
| 28 | CODE SEGMENT BYTE PUBLIC 'CODE' | ||
| 29 | ASSUME SS:DOSGROUP,CS:DOSGROUP | ||
| 30 | |||
| 31 | .xcref | ||
| 32 | INCLUDE DOSSYM.INC | ||
| 33 | INCLUDE DEVSYM.INC | ||
| 34 | .cref | ||
| 35 | .list | ||
| 36 | |||
| 37 | FastDiv = TRUE | ||
| 38 | |||
| 39 | i_need CURBUF,DWORD | ||
| 40 | i_need CLUSSPLIT,BYTE | ||
| 41 | i_need CLUSSAVE,WORD | ||
| 42 | i_need CLUSSEC,DWORD ;F.C. >32mb ;AN000; | ||
| 43 | i_need THISDRV,BYTE | ||
| 44 | i_need THISDPB,DWORD | ||
| 45 | i_need DEVCALL,BYTE | ||
| 46 | i_need CALLMED,BYTE | ||
| 47 | i_need CALLRBYT,BYTE | ||
| 48 | i_need BUFFHEAD,DWORD | ||
| 49 | i_need CALLXAD,DWORD | ||
| 50 | i_need CALLBPB,DWORD | ||
| 51 | i_need CDSADDR,DWORD | ||
| 52 | i_need CDSCOUNT,BYTE | ||
| 53 | i_need EXTERR,WORD | ||
| 54 | i_need EXTERRPT,DWORD | ||
| 55 | i_need CALLVIDM,DWORD | ||
| 56 | i_need ReadOp,BYTE | ||
| 57 | i_need FAILERR,BYTE | ||
| 58 | i_need ALLOWED,BYTE | ||
| 59 | i_need VOLCHNG_FLAG,BYTE | ||
| 60 | i_need HIGH_SECTOR,WORD | ||
| 61 | i_need BUF_HASH_COUNT,WORD | ||
| 62 | i_need BUF_HASH_PTR,DWORD | ||
| 63 | i_need FIRST_BUFF_ADDR,WORD | ||
| 64 | i_need SC_CACHE_COUNT,WORD ;AN001; | ||
| 65 | i_need CURSC_DRIVE,BYTE ;AN001; | ||
| 66 | |||
| 67 | |||
| 68 | Break <IsEOF - check the quantity in BX for EOF> | ||
| 69 | |||
| 70 | ; | ||
| 71 | ; IsEOF - check the fat value in BX for eof. | ||
| 72 | ; | ||
| 73 | ; Inputs: ES:BP point to DPB | ||
| 74 | ; BX has fat value | ||
| 75 | ; Outputs: JAE eof | ||
| 76 | ; Registers modified: none | ||
| 77 | Procedure IsEof,NEAR | ||
| 78 | ASSUME SS:DOSGROUP,CS:DOSGROUP,DS:NOTHING,ES:NOTHING | ||
| 79 | Assert ISDPB,<ES,BP>,"IsEOF" | ||
| 80 | CMP ES:[BP.dpb_max_cluster],4096-10 ; is this 16 bit fat? | ||
| 81 | JAE EOF16 ; yes, check for eof there | ||
| 82 | ;J.K. 8/27/86 | ||
| 83 | ;Modified to accept 0FF0h as an eof. This is to handle the diskfull case | ||
| 84 | ;of any media that has "F0"(Other) as a MediaByte. | ||
| 85 | ;Hopely, this does not create any side effect for those who may use any value | ||
| 86 | ;other than "FF8-FFF" as an Eof for their own file. | ||
| 87 | cmp bx,0FF0h | ||
| 88 | je IsEOF_other | ||
| 89 | CMP BX,0FF8h ; do the 12 bit compare | ||
| 90 | IsEOF_other: | ||
| 91 | return | ||
| 92 | EOF16: | ||
| 93 | CMP BX,0FFF8h ; 16 bit compare | ||
| 94 | return | ||
| 95 | EndProc IsEof | ||
| 96 | |||
| 97 | Break <UNPACK -- UNPACK FAT ENTRIES> | ||
| 98 | |||
| 99 | ; Inputs: | ||
| 100 | ; BX = Cluster number (may be full 16-bit quantity) | ||
| 101 | ; ES:BP = Base of drive parameters | ||
| 102 | ; Outputs: | ||
| 103 | ; DI = Contents of FAT for given cluster (may be full 16-bit quantity) | ||
| 104 | ; Zero set means DI=0 (free cluster) | ||
| 105 | ; Carry set means error (currently user FAILed to I 24) | ||
| 106 | ; SI Destroyed, No other registers affected. Fatal error if cluster too big. | ||
| 107 | |||
| 108 | procedure UNPACK,NEAR | ||
| 109 | DOSAssume CS,<DS>,"UnPack" | ||
| 110 | ASSUME ES:NOTHING | ||
| 111 | |||
| 112 | Assert ISDPB,<ES,BP>,"Unpack" | ||
| 113 | CMP BX,ES:[BP.dpb_max_cluster] | ||
| 114 | JA HURTFAT | ||
| 115 | CALL MAPCLUSTER | ||
| 116 | ASSUME DS:NOTHING | ||
| 117 | jc DoContext | ||
| 118 | MOV DI,[DI] | ||
| 119 | JNZ High12 ; MZ if high 12 bits, go get 'em | ||
| 120 | MOV SI,ES:[BP.dpb_max_cluster] ; MZ is this 16-bit fat? | ||
| 121 | CMP SI,4096-10 | ||
| 122 | JB Unpack12 ; MZ No, go 'AND' off bits | ||
| 123 | OR DI,DI ; MZ set zero condition code, clears carry | ||
| 124 | JMP SHORT DoContext ; MZ go do context | ||
| 125 | |||
| 126 | High12: | ||
| 127 | SHR DI,1 | ||
| 128 | SHR DI,1 | ||
| 129 | SHR DI,1 | ||
| 130 | SHR DI,1 | ||
| 131 | Unpack12: | ||
| 132 | AND DI,0FFFH ; Clears carry | ||
| 133 | DoContext: | ||
| 134 | PUSH SS | ||
| 135 | POP DS | ||
| 136 | return | ||
| 137 | |||
| 138 | HURTFAT: | ||
| 139 | MOV ES:[BP.dpb_free_cnt],-1 ; Err in FAT must force recomp of freespace | ||
| 140 | PUSH AX | ||
| 141 | MOV AH,allowed_fail + 80h | ||
| 142 | MOV Allowed,allowed_fail | ||
| 143 | ; | ||
| 144 | ; Signal Bad FAT to INT int_fatal_abort handler. We have an invalid cluster. | ||
| 145 | ; | ||
| 146 | MOV DI,0FFFH ; In case INT int_fatal_abort returns (it shouldn't) | ||
| 147 | invoke FATAL | ||
| 148 | CMP AL,3 | ||
| 149 | CLC | ||
| 150 | JNZ OKU_RET ; Try to ignore bad FAT | ||
| 151 | STC ; User said FAIL | ||
| 152 | OKU_RET: | ||
| 153 | POP AX | ||
| 154 | return | ||
| 155 | EndProc UNPACK | ||
| 156 | |||
| 157 | Break <PACK -- PACK FAT ENTRIES> | ||
| 158 | |||
| 159 | ; Inputs: | ||
| 160 | ; BX = Cluster number | ||
| 161 | ; DX = Data | ||
| 162 | ; ES:BP = Pointer to drive DPB | ||
| 163 | ; Outputs: | ||
| 164 | ; The data is stored in the FAT at the given cluster. | ||
| 165 | ; SI,DX,DI all destroyed | ||
| 166 | ; Carry set means error (currently user FAILed to I 24) | ||
| 167 | ; No other registers affected | ||
| 168 | |||
| 169 | procedure PACK,NEAR | ||
| 170 | DOSAssume CS,<DS>,"Pack" | ||
| 171 | ASSUME ES:NOTHING | ||
| 172 | |||
| 173 | Assert ISDPB,<ES,BP>,"Pack" | ||
| 174 | CALL MAPCLUSTER | ||
| 175 | ASSUME DS:NOTHING | ||
| 176 | JC DoContext | ||
| 177 | MOV SI,[DI] | ||
| 178 | JZ Aligned ; byte (not nibble) aligned | ||
| 179 | PUSH CX ; move data to upper 12 bits | ||
| 180 | MOV CL,4 | ||
| 181 | SHL DX,CL | ||
| 182 | POP CX | ||
| 183 | AND SI,0FH ; leave in original low 4 bits | ||
| 184 | JMP SHORT PACKIN | ||
| 185 | ALIGNED: | ||
| 186 | CMP ES:[BP.dpb_max_cluster],4096-10 ; MZ 16 bit fats? | ||
| 187 | JAE Pack16 ; MZ yes, go clobber original data | ||
| 188 | AND SI,0F000H ; MZ leave in upper 4 bits of original | ||
| 189 | AND DX,0FFFh ; MZ store only 12 bits | ||
| 190 | JMP SHORT PackIn ; MZ go store | ||
| 191 | Pack16: | ||
| 192 | XOR SI,SI ; MZ no original data | ||
| 193 | PACKIN: | ||
| 194 | OR SI,DX | ||
| 195 | MOV [DI],SI | ||
| 196 | LDS SI,[CURBUF] | ||
| 197 | TEST [SI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; | ||
| 198 | JNZ yesdirty ;LB. don't increment dirty count ;AN000; | ||
| 199 | invoke INC_DIRTY_COUNT ;LB. ;AN000; | ||
| 200 | OR [SI.buf_flags],buf_dirty ;LB. ;AN000; | ||
| 201 | yesdirty: ;LB. ;AN000; | ||
| 202 | CMP BYTE PTR [CLUSSPLIT],0 | ||
| 203 | Context DS | ||
| 204 | retz ; Carry clear | ||
| 205 | PUSH AX | ||
| 206 | PUSH BX | ||
| 207 | PUSH CX | ||
| 208 | MOV AX,[CLUSSAVE] | ||
| 209 | MOV DS,WORD PTR [CURBUF+2] | ||
| 210 | ASSUME DS:NOTHING | ||
| 211 | ADD SI,BUFINSIZ | ||
| 212 | MOV [SI],AH | ||
| 213 | Context DS | ||
| 214 | PUSH AX | ||
| 215 | MOV DX,WORD PTR [CLUSSEC+2] ;F.C. >32mb ;AN000; | ||
| 216 | MOV WORD PTR [HIGH_SECTOR],DX ;F.C. >32mb ;AN000; | ||
| 217 | |||
| 218 | MOV DX,WORD PTR [CLUSSEC] | ||
| 219 | MOV SI,1 | ||
| 220 | XOR AL,AL | ||
| 221 | invoke GETBUFFRB | ||
| 222 | POP AX | ||
| 223 | JC POPP_RET | ||
| 224 | LDS DI,[CURBUF] | ||
| 225 | ASSUME DS:NOTHING | ||
| 226 | TEST [DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; | ||
| 227 | JNZ yesdirty2 ;LB. don't increment dirty count ;AN000; | ||
| 228 | invoke INC_DIRTY_COUNT ;LB. ;AN000; | ||
| 229 | OR [DI.buf_flags],buf_dirty | ||
| 230 | yesdirty2: | ||
| 231 | ADD DI,BUFINSIZ | ||
| 232 | DEC DI | ||
| 233 | ADD DI,ES:[BP.dpb_sector_size] | ||
| 234 | MOV [DI],AL | ||
| 235 | CLC | ||
| 236 | POPP_RET: | ||
| 237 | PUSH SS | ||
| 238 | POP DS | ||
| 239 | POP CX | ||
| 240 | POP BX | ||
| 241 | POP AX | ||
| 242 | return | ||
| 243 | |||
| 244 | EndProc PACK | ||
| 245 | |||
| 246 | Break <MAPCLUSTER - BUFFER A FAT SECTOR> | ||
| 247 | |||
| 248 | ; Inputs: | ||
| 249 | ; ES:BP Points to DPB | ||
| 250 | ; BX Is cluster number | ||
| 251 | ; Function: | ||
| 252 | ; Get a pointer to the cluster | ||
| 253 | ; Outputs: | ||
| 254 | ; DS:DI Points to contents of FAT for given cluster | ||
| 255 | ; DS:SI Points to start of buffer | ||
| 256 | ; Zero Not set if cluster data is in high 12 bits of word | ||
| 257 | ; Zero set if cluster data is in low 12 or 16 bits | ||
| 258 | ; Carry set if failed. | ||
| 259 | ; SI is destroyed. | ||
| 260 | |||
| 261 | procedure MAPCLUSTER,NEAR | ||
| 262 | DOSAssume CS,<DS>,"MapCluster" | ||
| 263 | ASSUME ES:NOTHING | ||
| 264 | |||
| 265 | Assert ISDPB,<ES,BP>,"MapCluster" | ||
| 266 | MOV BYTE PTR [CLUSSPLIT],0 | ||
| 267 | SaveReg <AX,BX,CX,DX> | ||
| 268 | MOV AX,BX ; AX = BX | ||
| 269 | MOV CX,4096-10 | ||
| 270 | CMP ES:[BP.dpb_max_cluster],CX ; MZ 16 bit fat? | ||
| 271 | JAE Map16 ; MZ yes, do 16 bit algorithm | ||
| 272 | SHR AX,1 ; AX = BX/2 | ||
| 273 | Map16: ; MZ skip prev => AX=2*BX | ||
| 274 | XOR DI,DI ; >32mb fat ;AN000; | ||
| 275 | ADD AX,BX ; AX = 1.5*fat = byte offset in fat | ||
| 276 | ADC DI,0 ; >32mb fat ;AN000; | ||
| 277 | DoConvert: | ||
| 278 | MOV CX,ES:[BP.dpb_sector_size] | ||
| 279 | IF FastDiv | ||
| 280 | ; | ||
| 281 | ; Gross hack: 99% of all disks have 512 bytes per sector. We test for this | ||
| 282 | ; case and apply a really fast algorithm to get the desired results | ||
| 283 | ; | ||
| 284 | ; Divide method takes 158 (XOR and DIV) | ||
| 285 | ; Fast method takes 20 | ||
| 286 | ; | ||
| 287 | ; This saves a bunch. | ||
| 288 | ; | ||
| 289 | CMP CX,512 ; 4 Is this 512 byte sector? | ||
| 290 | JZ Nodiv ;F.C. >32mb ;AN000; | ||
| 291 | JMP DoDiv ; 4/16 No, go do divide | ||
| 292 | Nodiv: ;F.C. >32mb ;AN000; | ||
| 293 | MOV DX,AX ; 2 get set for remainder | ||
| 294 | AND DX,512-1 ; 4 Form remainder | ||
| 295 | MOV AL,AH ; 2 | ||
| 296 | SHR AL,1 ; 2 | ||
| 297 | CBW ; 2 Fast divide by 512 | ||
| 298 | OR DI,DI ;>32mb >64k ? ;AN000; | ||
| 299 | JZ g64k ;>32mb no ;AN000; | ||
| 300 | OR AX,80H ;>32mb ;AN000; | ||
| 301 | g64k: | ||
| 302 | ELSE | ||
| 303 | XOR DX,DX ; 3 | ||
| 304 | DIV CX ; 155 AX is FAT sector # DX is sector index | ||
| 305 | ENDIF | ||
| 306 | DivDone: | ||
| 307 | ADD AX,ES:[BP.dpb_first_FAT] | ||
| 308 | DEC CX ; CX is sector size - 1 | ||
| 309 | SaveReg <AX,DX,CX> | ||
| 310 | MOV DX,AX | ||
| 311 | MOV [HIGH_SECTOR],0 ;F.C. >32mb low sector # | ||
| 312 | XOR AL,AL | ||
| 313 | MOV SI,1 | ||
| 314 | invoke GETBUFFRB | ||
| 315 | RestoreReg <CX,AX,DX> ; CX is sec siz-1, AX is offset in sec | ||
| 316 | JC MAP_POP | ||
| 317 | LDS SI,[CURBUF] | ||
| 318 | ASSUME DS:NOTHING | ||
| 319 | LEA DI,[SI.BufInSiz] | ||
| 320 | ADD DI,AX | ||
| 321 | CMP AX,CX | ||
| 322 | JNZ MAPRET | ||
| 323 | MOV AL,[DI] | ||
| 324 | Context DS | ||
| 325 | INC BYTE PTR [CLUSSPLIT] | ||
| 326 | MOV BYTE PTR [CLUSSAVE],AL | ||
| 327 | MOV WORD PTR [CLUSSEC],DX | ||
| 328 | MOV WORD PTR [CLUSSEC+2],0 ;F.C. >32mb ;AN000; | ||
| 329 | INC DX | ||
| 330 | MOV [HIGH_SECTOR],0 ;F.C. >32mb FAT sector <32mb ;AN000; | ||
| 331 | XOR AL,AL | ||
| 332 | MOV SI,1 | ||
| 333 | invoke GETBUFFRB | ||
| 334 | JC MAP_POP | ||
| 335 | LDS SI,[CURBUF] | ||
| 336 | ASSUME DS:NOTHING | ||
| 337 | LEA DI,[SI.BufInSiz] | ||
| 338 | MOV AL,[DI] | ||
| 339 | Context DS | ||
| 340 | MOV BYTE PTR [CLUSSAVE+1],AL | ||
| 341 | MOV DI,OFFSET DOSGROUP:CLUSSAVE | ||
| 342 | MAPRET: | ||
| 343 | RestoreReg <DX,CX,BX> | ||
| 344 | XOR AX,AX ; MZ allow shift to clear carry | ||
| 345 | CMP ES:[BP.dpb_max_cluster],4096-10 ; MZ is this 16-bit fat? | ||
| 346 | JAE MapSet ; MZ no, set flags | ||
| 347 | MOV AX,BX | ||
| 348 | MapSet: | ||
| 349 | TEST AL,1 ; set zero flag if not on boundary | ||
| 350 | RestoreReg <AX> | ||
| 351 | return | ||
| 352 | |||
| 353 | MAP_POP: | ||
| 354 | RestoreReg <DX,CX,BX,AX> | ||
| 355 | return | ||
| 356 | IF FastDiv | ||
| 357 | DoDiv: | ||
| 358 | XOR DX,DX ; 3 | ||
| 359 | DIV CX ; 155 AX is FAT sector # DX is sector index | ||
| 360 | JMP DivDone ;15 total=35 | ||
| 361 | ENDIF | ||
| 362 | |||
| 363 | EndProc MAPCLUSTER | ||
| 364 | |||
| 365 | Break <FATREAD_SFT/FATREAD_CDS -- CHECK DRIVE GET FAT> | ||
| 366 | |||
| 367 | ; Inputs: | ||
| 368 | ; ES:DI points to an SFT for the drive of intrest (local only, | ||
| 369 | ; giving a NET SFT will produce system crashing results). | ||
| 370 | ; DS DOSGROUP | ||
| 371 | ; Function: | ||
| 372 | ; Can be used by an SFT routine (like CLOSE) to invalidate buffers | ||
| 373 | ; if disk changed. | ||
| 374 | ; In other respects, same as FATREAD_CDS. | ||
| 375 | ; (note ES:DI destroyed!) | ||
| 376 | ; Outputs: | ||
| 377 | ; Carry set if error (currently user FAILed to I 24) | ||
| 378 | ; NOTE: This routine may cause FATREAD_CDS to "miss" a disk change | ||
| 379 | ; as far as invalidating curdir_ID is concerned. | ||
| 380 | ; Since getting a true disk changed on this call is a screw up | ||
| 381 | ; anyway, that's the way it goes. | ||
| 382 | |||
| 383 | procedure FATREAD_SFT,NEAR | ||
| 384 | DOSAssume CS,<DS>,"FATRead_SFT" | ||
| 385 | ASSUME ES:NOTHING | ||
| 386 | |||
| 387 | LES BP,ES:[DI.sf_devptr] | ||
| 388 | Assert ISDPB,<ES,BP>,"FatReadSFT" | ||
| 389 | MOV AL,ES:[BP.dpb_drive] | ||
| 390 | MOV [THISDRV],AL | ||
| 391 | invoke GOTDPB ;Set THISDPB | ||
| 392 | CALL FAT_GOT_DPB | ||
| 393 | return | ||
| 394 | EndProc FATREAD_SFT | ||
| 395 | |||
| 396 | ; Inputs: | ||
| 397 | ; DS:DOSGROUP | ||
| 398 | ; ES:DI points to an CDS for the drive of intrest (local only, | ||
| 399 | ; giving a NET or NUL CDS will produce system crashing results). | ||
| 400 | ; Function: | ||
| 401 | ; If disk may have been changed, media is determined and buffers are | ||
| 402 | ; flagged invalid. If not, no action is taken. | ||
| 403 | ; Outputs: | ||
| 404 | ; ES:BP = Drive parameter block | ||
| 405 | ; [THISDPB] = ES:BP | ||
| 406 | ; [THISDRV] set | ||
| 407 | ; Carry set if error (currently user FAILed to I 24) | ||
| 408 | ; DS preserved , all other registers destroyed | ||
| 409 | |||
| 410 | procedure FATREAD_CDS,NEAR | ||
| 411 | DOSAssume CS,<DS>,"FATRead_CDS" | ||
| 412 | ASSUME ES:NOTHING | ||
| 413 | |||
| 414 | PUSH ES | ||
| 415 | PUSH DI | ||
| 416 | LES BP,ES:[DI.curdir_devptr] | ||
| 417 | Assert ISDPB,<ES,BP>,"FatReadCDS" | ||
| 418 | MOV AL,ES:[BP.dpb_drive] | ||
| 419 | MOV [THISDRV],AL | ||
| 420 | invoke GOTDPB ;Set THISDPB | ||
| 421 | CALL FAT_GOT_DPB | ||
| 422 | POP DI ;Get back CDS pointer | ||
| 423 | POP ES | ||
| 424 | retc | ||
| 425 | JNZ NO_CHANGE ;Media NOT changed | ||
| 426 | ; Media changed. We now need to find all CDS structures which use this | ||
| 427 | ; DPB and invalidate their ID pointers. | ||
| 428 | MED_CHANGE: | ||
| 429 | XOR AX,AX | ||
| 430 | DEC AX ;AX = -1 | ||
| 431 | PUSH DS | ||
| 432 | MOV CL,[CDSCOUNT] | ||
| 433 | XOR CH,CH ; CX is number of structures | ||
| 434 | LDS SI,ES:[DI.curdir_devptr] ; Find all CDS with this devptr | ||
| 435 | ASSUME DS:NOTHING | ||
| 436 | LES DI,[CDSADDR] ; Start here | ||
| 437 | CHECK_CDS: | ||
| 438 | TEST ES:[DI.curdir_flags],curdir_isnet | ||
| 439 | JNZ NEXTCDS ; Leave NET guys alone!! | ||
| 440 | PUSH ES | ||
| 441 | PUSH DI | ||
| 442 | LES DI,ES:[DI.curdir_devptr] | ||
| 443 | invoke POINTCOMP | ||
| 444 | POP DI | ||
| 445 | POP ES | ||
| 446 | JNZ NEXTCDS ; CDS not for this drive | ||
| 447 | TEST ES:[DI.curdir_ID],AX | ||
| 448 | JZ NEXTCDS ; If root, leave root | ||
| 449 | MOV ES:[DI.curdir_ID],AX ; else invalid | ||
| 450 | NEXTCDS: | ||
| 451 | ADD DI,SIZE curdir_list ; Point to next CDS | ||
| 452 | LOOP CHECK_CDS | ||
| 453 | POP DS | ||
| 454 | DOSAssume CS,<DS>,"FAT/NextCDS" | ||
| 455 | NO_CHANGE: | ||
| 456 | LES BP,[THISDPB] | ||
| 457 | CLC | ||
| 458 | return | ||
| 459 | EndProc FATREAD_CDS | ||
| 460 | |||
| 461 | Break <Fat_Operation - miscellaneous fat stuff> | ||
| 462 | |||
| 463 | procedure FAT_operation,NEAR | ||
| 464 | FATERR: | ||
| 465 | DOSAssume CS,<DS>,"FATERR" | ||
| 466 | MOV ES:[BP.dpb_free_cnt],-1 ; Err in FAT must force recomp of freespace | ||
| 467 | AND DI,STECODE ; Put error code in DI | ||
| 468 | MOV [ALLOWED],allowed_FAIL + allowed_RETRY | ||
| 469 | MOV AH,2 + allowed_FAIL + allowed_RETRY ; While trying to read FAT | ||
| 470 | MOV AL,BYTE PTR [THISDRV] ; Tell which drive | ||
| 471 | invoke FATAL1 | ||
| 472 | LES BP,[THISDPB] | ||
| 473 | CMP AL,3 | ||
| 474 | JNZ FAT_GOT_DPB ; User said retry | ||
| 475 | STC ; User said FAIL | ||
| 476 | return | ||
| 477 | |||
| 478 | FAT_GOT_DPB: | ||
| 479 | Context DS | ||
| 480 | MOV AL,DMEDHL | ||
| 481 | MOV AH,ES:[BP.dpb_UNIT] | ||
| 482 | MOV WORD PTR [DEVCALL],AX | ||
| 483 | MOV BYTE PTR [DEVCALL.REQFUNC],DEVMDCH | ||
| 484 | MOV [DEVCALL.REQSTAT],0 | ||
| 485 | MOV AL,ES:[BP.dpb_media] | ||
| 486 | MOV BYTE PTR [CALLMED],AL | ||
| 487 | PUSH ES | ||
| 488 | PUSH DS | ||
| 489 | MOV BX,OFFSET DOSGROUP:DEVCALL | ||
| 490 | LDS SI,ES:[BP.dpb_driver_addr] ; DS:SI Points to device header | ||
| 491 | ASSUME DS:NOTHING | ||
| 492 | POP ES ; ES:BX Points to call header | ||
| 493 | invoke DEVIOCALL2 | ||
| 494 | Context DS | ||
| 495 | POP ES ; Restore ES:BP | ||
| 496 | MOV DI,[DEVCALL.REQSTAT] | ||
| 497 | TEST DI,STERR | ||
| 498 | JNZ FATERR | ||
| 499 | XOR AH,AH | ||
| 500 | XCHG AH,ES:[BP.dpb_first_access] ; Reset dpb_first_access | ||
| 501 | MOV AL,BYTE PTR [THISDRV] ; Use physical unit number | ||
| 502 | ; See if we had changed volume id by creating one on the diskette | ||
| 503 | cmp [VOLCHNG_FLAG],AL | ||
| 504 | jnz CHECK_BYT | ||
| 505 | mov [VOLCHNG_FLAG],-1 | ||
| 506 | jmp GOGETBPB ; Need to get device driver to read in | ||
| 507 | ; new volume label. | ||
| 508 | CHECK_BYT: | ||
| 509 | OR AH,BYTE PTR [CALLRBYT] | ||
| 510 | JNS CHECK_ZR ; ns = 0 or 1 | ||
| 511 | JMP NEWDSK | ||
| 512 | |||
| 513 | CHECK_ZR: | ||
| 514 | JZ CHKBUFFDIRT ; jump if I don't know | ||
| 515 | CLC | ||
| 516 | return ; If Media not changed (NZ) | ||
| 517 | |||
| 518 | DISK_CHNG_ERR: | ||
| 519 | ASSUME DS:NOTHING | ||
| 520 | PUSH ES | ||
| 521 | PUSH BP | ||
| 522 | LES BP,ES:[BP.dpb_driver_addr] ; Get device pointer | ||
| 523 | TEST ES:[BP.SDEVATT],DEVOPCL ; Did it set vol id? | ||
| 524 | POP BP | ||
| 525 | POP ES | ||
| 526 | JZ FAIL_OPJ2 ; Nope, FAIL | ||
| 527 | PUSH DS ; Save buffer pointer for ignore | ||
| 528 | PUSH DI | ||
| 529 | Context DS | ||
| 530 | MOV [ALLOWED],allowed_FAIL + allowed_RETRY | ||
| 531 | PUSH ES | ||
| 532 | LES DI,[CALLVIDM] ; Get volume ID pointer | ||
| 533 | MOV WORD PTR [EXTERRPT+2],ES | ||
| 534 | POP ES | ||
| 535 | MOV WORD PTR [EXTERRPT],DI | ||
| 536 | MOV AX,error_I24_wrong_disk | ||
| 537 | MOV [READOP],1 ; Write | ||
| 538 | invoke HARDERR | ||
| 539 | POP DI ; Get back buffer for ignore | ||
| 540 | POP DS | ||
| 541 | ASSUME DS:NOTHING | ||
| 542 | CMP AL,3 | ||
| 543 | FAIL_OPJ2: | ||
| 544 | JZ FAIL_OP | ||
| 545 | JMP FAT_GOT_DPB ; Retry | ||
| 546 | |||
| 547 | CHKBUFFDIRT: | ||
| 548 | DOSAssume CS,<DS>,"FAT/ChkBuffDirt" | ||
| 549 | ; LDS DI,[BUFFHEAD] | ||
| 550 | ASSUME DS:NOTHING | ||
| 551 | XOR DX,DX ;LB. ;AN000; | ||
| 552 | LDS DI,[BUF_HASH_PTR] ;LB. scan from 1st entry ;AN000; | ||
| 553 | MOV CX,[BUF_HASH_COUNT] ;LB. get Hash entry count ;AN000; | ||
| 554 | |||
| 555 | scan_dirty: | ||
| 556 | CMP [DI.Dirty_Count],0 ;LB. if not dirty ;AN000; | ||
| 557 | JZ GETNEXT ;LB. get next hash entry ;AN000; | ||
| 558 | PUSH DS ;LB. save hash entry addr ;AN000; | ||
| 559 | PUSH DI ;LB. ;AN000; | ||
| 560 | invoke Map_Entry ;LB. ;AN000; | ||
| 561 | NBUFFER: ; Look for dirty buffers | ||
| 562 | CMP AL,[DI.buf_ID] | ||
| 563 | JNZ LFNXT ; Not for this unit | ||
| 564 | TEST [DI.buf_flags],buf_dirty | ||
| 565 | JZ LFNXT | ||
| 566 | POP DI ;LB. restore regs ;AN000; | ||
| 567 | POP DS ;LB. ;AN000; | ||
| 568 | Context DS | ||
| 569 | CLC | ||
| 570 | return ; There is a dirty buffer, assume Media OK (NZ) | ||
| 571 | |||
| 572 | FAIL_OP: | ||
| 573 | Context DS | ||
| 574 | STC | ||
| 575 | return | ||
| 576 | |||
| 577 | ASSUME DS:NOTHING | ||
| 578 | LFNXT: | ||
| 579 | mov DI,[DI.buf_next] ;; 1/19/88 | ||
| 580 | CMP DI,[FIRST_BUFF_ADDR] ;; 1/19/88 | ||
| 581 | JNZ NBUFFER | ||
| 582 | POP DI ;LB. restore regs ;AN000; | ||
| 583 | POP DS ;LB. ;AN000; | ||
| 584 | GETNEXT: | ||
| 585 | ADD DI,size BUFFER_HASH_ENTRY ;LB. next entry ;AN000; | ||
| 586 | LOOP scan_dirty ;LB. scan next entry ;AN000; | ||
| 587 | ; If no dirty buffers, assume Media changed | ||
| 588 | NEWDSK: | ||
| 589 | MOV ES:[BP.dpb_free_cnt],-1 ; Media changed, must re-compute | ||
| 590 | ; NOTE: It is TECHNICALLY more correct | ||
| 591 | ASSUME DS:NOTHING | ||
| 592 | XOR DX,DX ;LB. ;AN000; | ||
| 593 | MOV [HIGH_SECTOR],DX ;LB. scan from 1st entry ;AN000; | ||
| 594 | MOV CX,[BUF_HASH_COUNT] ;LB. get Hash entry count ;AN000; | ||
| 595 | |||
| 596 | NxtHash: | ||
| 597 | invoke GETCURHEAD ;LB. get Hash entry buffer header ;AN000; | ||
| 598 | ; to do this AFTER the check for | ||
| 599 | ASSUME DS:NOTHING | ||
| 600 | NXBUFFER: | ||
| 601 | CMP AL,[DI.buf_ID] ; For this drive? | ||
| 602 | JZ OLDDRV2 ;LB. yes ;AN000; | ||
| 603 | mov DI,[DI.buf_next] ;LB. get next buffer 1/19/88 ;AN000; | ||
| 604 | JMP SHORT SKPBUFF ;LB. ;AN000; | ||
| 605 | OLDDRV2: | ||
| 606 | TEST [DI.buf_flags],buf_dirty | ||
| 607 | JZ OldDrv | ||
| 608 | JMP Disk_Chng_Err ; Disk changed but dirty buffers | ||
| 609 | OLDDRV: | ||
| 610 | MOV WORD PTR [DI.buf_ID],(buf_visit SHL 8) OR 0FFH ; Free up buffer | ||
| 611 | invoke SCANPLACE | ||
| 612 | SKPBUFF: | ||
| 613 | CMP DI,[FIRST_BUFF_ADDR] ;LB. end of chain 1/19/88 ;AN000; | ||
| 614 | JNZ NXBUFFER ;LB. no ;AN000; | ||
| 615 | INC DX ;LB. ;AN000; | ||
| 616 | LOOP NxtHash ;LB. ;AN000; | ||
| 617 | CMP [SC_CACHE_COUNT],0 ;LB. look ahead buffers ? ;AN001; | ||
| 618 | JZ GOGETBPB ;LB. no ;AN001; | ||
| 619 | CMP AL,[CURSC_DRIVE] ;LB. same as changed drive ;AN001; | ||
| 620 | JNZ GOGETBPB ;LB. no ;AN001; | ||
| 621 | MOV [CURSC_DRIVE],-1 ;LB. invalidate look ahead buffers ;AN000; | ||
| 622 | GOGETBPB: | ||
| 623 | LDS DI,ES:[BP.dpb_driver_addr] | ||
| 624 | TEST [DI.SDEVATT],ISFATBYDEV | ||
| 625 | JNZ GETFREEBUF | ||
| 626 | context DS | ||
| 627 | MOV BX,2 | ||
| 628 | CALL UNPACK ; Read the first FAT sector into CURBUF | ||
| 629 | FAIL_OPJ: | ||
| 630 | JC FAIL_OP | ||
| 631 | LDS DI,[CURBUF] | ||
| 632 | ASSUME DS:NOTHING | ||
| 633 | JMP SHORT GOTGETBUF | ||
| 634 | |||
| 635 | GETFREEBUF: | ||
| 636 | ASSUME DS:NOTHING | ||
| 637 | PUSH ES ; Get a free buffer for BIOS to use | ||
| 638 | PUSH BP | ||
| 639 | ; LDS DI,[BUFFHEAD] | ||
| 640 | XOR DX,DX ;LB. fake to get 1st ;AN000; | ||
| 641 | MOV [HIGH_SECTOR],DX ;LB. buffer addr ;AN000; | ||
| 642 | invoke GETCURHEAD ;LB. ;AN000; | ||
| 643 | |||
| 644 | invoke BUFWRITE | ||
| 645 | POP BP | ||
| 646 | POP ES | ||
| 647 | JC FAIL_OPJ | ||
| 648 | GOTGETBUF: | ||
| 649 | ADD DI,BUFINSIZ | ||
| 650 | MOV WORD PTR [CALLXAD+2],DS | ||
| 651 | Context DS | ||
| 652 | MOV WORD PTR [CALLXAD],DI | ||
| 653 | MOV AL,DBPBHL | ||
| 654 | MOV AH,BYTE PTR ES:[BP.dpb_UNIT] | ||
| 655 | MOV WORD PTR [DEVCALL],AX | ||
| 656 | MOV BYTE PTR [DEVCALL.REQFUNC],DEVBPB | ||
| 657 | MOV [DEVCALL.REQSTAT],0 | ||
| 658 | MOV AL,BYTE PTR ES:[BP.dpb_media] | ||
| 659 | MOV [CALLMED],AL | ||
| 660 | PUSH ES | ||
| 661 | PUSH DS | ||
| 662 | PUSH WORD PTR ES:[BP.dpb_driver_addr+2] | ||
| 663 | PUSH WORD PTR ES:[BP.dpb_driver_addr] | ||
| 664 | MOV BX,OFFSET DOSGROUP:DEVCALL | ||
| 665 | POP SI | ||
| 666 | POP DS ; DS:SI Points to device header | ||
| 667 | ASSUME DS:NOTHING | ||
| 668 | POP ES ; ES:BX Points to call header | ||
| 669 | invoke DEVIOCALL2 | ||
| 670 | POP ES ; Restore ES:BP | ||
| 671 | Context DS | ||
| 672 | MOV DI,[DEVCALL.REQSTAT] | ||
| 673 | TEST DI,STERR | ||
| 674 | JNZ FATERRJ | ||
| 675 | MOV AL,BYTE PTR ES:[BP.dpb_media] | ||
| 676 | LDS SI,[CALLBPB] | ||
| 677 | ASSUME DS:NOTHING | ||
| 678 | MOV ES:[BP].DPB_next_free,0 ; recycle scanning pointer | ||
| 679 | invoke $SETDPB | ||
| 680 | LDS DI,[CALLXAD] ; Get back buffer pointer | ||
| 681 | MOV AL,BYTE PTR ES:[BP.dpb_FAT_count] | ||
| 682 | MOV [DI.buf_wrtcnt-BUFINSIZ],AL ;>32mb ;AN000; | ||
| 683 | MOV AX,ES:[BP.dpb_FAT_size] ;>32mb ;AC000; | ||
| 684 | MOV [DI.buf_wrtcntinc-BUFINSIZ],AX ;>32mb Correct buffer info ;AC000; | ||
| 685 | |||
| 686 | Context DS | ||
| 687 | XOR AL,AL ;Media changed (Z), Carry clear | ||
| 688 | return | ||
| 689 | |||
| 690 | FATERRJ: JMP FATERR | ||
| 691 | |||
| 692 | EndProc FAT_operation | ||
| 693 | |||
| 694 | CODE ENDS | ||
| 695 | END | ||