summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/FAT.ASM
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--v4.0/src/DOS/FAT.ASM695
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
3TITLE FAT - FAT maintenance routines
4NAME 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
26include dosseg.asm
27
28CODE SEGMENT BYTE PUBLIC 'CODE'
29 ASSUME SS:DOSGROUP,CS:DOSGROUP
30
31.xcref
32INCLUDE DOSSYM.INC
33INCLUDE DEVSYM.INC
34.cref
35.list
36
37FastDiv = 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
68Break <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
77Procedure 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
90IsEOF_other:
91 return
92EOF16:
93 CMP BX,0FFF8h ; 16 bit compare
94 return
95EndProc IsEof
96
97Break <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
116ASSUME 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
126High12:
127 SHR DI,1
128 SHR DI,1
129 SHR DI,1
130 SHR DI,1
131Unpack12:
132 AND DI,0FFFH ; Clears carry
133DoContext:
134 PUSH SS
135 POP DS
136 return
137
138HURTFAT:
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
152OKU_RET:
153 POP AX
154 return
155EndProc UNPACK
156
157Break <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
175ASSUME 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
185ALIGNED:
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
191Pack16:
192 XOR SI,SI ; MZ no original data
193PACKIN:
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;
201yesdirty: ;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]
210ASSUME 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]
225ASSUME 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
230yesdirty2:
231 ADD DI,BUFINSIZ
232 DEC DI
233 ADD DI,ES:[BP.dpb_sector_size]
234 MOV [DI],AL
235 CLC
236POPP_RET:
237 PUSH SS
238 POP DS
239 POP CX
240 POP BX
241 POP AX
242 return
243
244EndProc PACK
245
246Break <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
273Map16: ; 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;
277DoConvert:
278 MOV CX,ES:[BP.dpb_sector_size]
279IF 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
292Nodiv: ;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;
301g64k:
302ELSE
303 XOR DX,DX ; 3
304 DIV CX ; 155 AX is FAT sector # DX is sector index
305ENDIF
306DivDone:
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]
318ASSUME 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]
336ASSUME 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
342MAPRET:
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
348MapSet:
349 TEST AL,1 ; set zero flag if not on boundary
350 RestoreReg <AX>
351 return
352
353MAP_POP:
354 RestoreReg <DX,CX,BX,AX>
355 return
356IF FastDiv
357DoDiv:
358 XOR DX,DX ; 3
359 DIV CX ; 155 AX is FAT sector # DX is sector index
360 JMP DivDone ;15 total=35
361ENDIF
362
363EndProc MAPCLUSTER
364
365Break <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
394EndProc 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.
428MED_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
435ASSUME DS:NOTHING
436 LES DI,[CDSADDR] ; Start here
437CHECK_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
450NEXTCDS:
451 ADD DI,SIZE curdir_list ; Point to next CDS
452 LOOP CHECK_CDS
453 POP DS
454 DOSAssume CS,<DS>,"FAT/NextCDS"
455NO_CHANGE:
456 LES BP,[THISDPB]
457 CLC
458 return
459EndProc FATREAD_CDS
460
461Break <Fat_Operation - miscellaneous fat stuff>
462
463 procedure FAT_operation,NEAR
464FATERR:
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
478FAT_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
491ASSUME 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.
508CHECK_BYT:
509 OR AH,BYTE PTR [CALLRBYT]
510 JNS CHECK_ZR ; ns = 0 or 1
511 JMP NEWDSK
512
513CHECK_ZR:
514 JZ CHKBUFFDIRT ; jump if I don't know
515 CLC
516 return ; If Media not changed (NZ)
517
518DISK_CHNG_ERR:
519ASSUME 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
541ASSUME DS:NOTHING
542 CMP AL,3
543FAIL_OPJ2:
544 JZ FAIL_OP
545 JMP FAT_GOT_DPB ; Retry
546
547CHKBUFFDIRT:
548 DOSAssume CS,<DS>,"FAT/ChkBuffDirt"
549; LDS DI,[BUFFHEAD]
550ASSUME 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
555scan_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;
561NBUFFER: ; 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
572FAIL_OP:
573 Context DS
574 STC
575 return
576
577ASSUME DS:NOTHING
578LFNXT:
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;
584GETNEXT:
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
588NEWDSK:
589 MOV ES:[BP.dpb_free_cnt],-1 ; Media changed, must re-compute
590 ; NOTE: It is TECHNICALLY more correct
591ASSUME 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
596NxtHash:
597 invoke GETCURHEAD ;LB. get Hash entry buffer header ;AN000;
598 ; to do this AFTER the check for
599ASSUME DS:NOTHING
600NXBUFFER:
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;
605OLDDRV2:
606 TEST [DI.buf_flags],buf_dirty
607 JZ OldDrv
608 JMP Disk_Chng_Err ; Disk changed but dirty buffers
609OLDDRV:
610 MOV WORD PTR [DI.buf_ID],(buf_visit SHL 8) OR 0FFH ; Free up buffer
611 invoke SCANPLACE
612SKPBUFF:
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;
622GOGETBPB:
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
629FAIL_OPJ:
630 JC FAIL_OP
631 LDS DI,[CURBUF]
632ASSUME DS:NOTHING
633 JMP SHORT GOTGETBUF
634
635GETFREEBUF:
636ASSUME 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
648GOTGETBUF:
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
667ASSUME 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]
677ASSUME 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
690FATERRJ: JMP FATERR
691
692EndProc FAT_operation
693
694CODE ENDS
695 END