1 ; SCCSID = @(#)rom.asm 1.1 85/04/10
2 TITLE ROM
- Miscellaneous routines
4 ; Misc Low level routines for doing simple FCB computations, Cache
5 ; reads and writes, I/O optimization, and FAT allocation/deallocation
21 ; Modification history:
23 ; Created: ARR 30 March 1983
27 ; get the appropriate segment definitions
31 include fastseek
.inc ; DOS 4.00
32 include fastxxxx
.inc ; DOS 4.00
35 CODE SEGMENT BYTE PUBLIC 'CODE'
36 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
48 i_need SECCLUSPOS
,BYTE
56 i_need SECPOS
,DWORD ;F.C. >32mb
57 i_need VALSEC
,DWORD ;F.C. >32mb
59 i_need FSeek_drive
,BYTE ; DOS 3.4
60 i_need FSeek_firclus
,WORD ; DOS 3.4
61 i_need FSeek_logclus
,WORD ; DOS 3.4
62 i_need FSeek_logsave
,WORD ; DOS 3.4
63 i_need FastSeekFlg
,BYTE ; DOS 3.4
64 i_need XA_condition
,BYTE ; DOS 3.4
65 i_need HIGH_SECTOR
,WORD ; DOS 3.4
66 i_need DISK_FULL
,BYTE ; DOS 3.4
67 i_need Temp_VAR2
,WORD ; DOS 3.4
71 Break <FNDCLUS
-- Skip over allocation units
>
74 ; CX = No. of clusters to skip
75 ; ES:BP = Base of drive parameters
76 ; [THISSFT] point to SFT
78 ; BX = Last cluster skipped to
79 ; CX = No. of clusters remaining (0 unless EOF)
80 ; DX = Position of last cluster
81 ; Carry set if error (currently user FAILed to I 24)
82 ; DI destroyed. No other registers affected.
84 procedure FNDCLUS
,NEAR
85 DOSAssume
CS,<DS>,"FndClus"
88 Assert ISDPB
,<ES,BP>,"FndCLus"
92 Assert ISSFT
,<ES,DI>,"FndClus"
93 MOV [FSeek_logclus
],CX ; presume CX is the position ;AN000;
94 MOV BX,ES:[DI.sf_lstclus
]
95 MOV DX,ES:[DI.sf_cluspos
]
105 MOV BX,ES:[DI.sf_firclus
]
116 TEST [FastSeekflg
],Fast_yes
; fastseek installed? ;AN000;
117 JZ do_norm
; no ;AN000;
118 TEST [FastSeekflg
],FS_begin
; do fastseek ;AN000;
119 JZ do_norm
; no ;AN000;
120 TEST [FastSeekflg
],FS_insert
; is in insert mode ? ;AN000;
121 JNZ do_norm
; yes ;AN000;
122 MOV [Temp_Var2
],BX ; save physical cluster ;AN000;
125 invoke FastSeek_Lookup
; ask for next cluster # ;AN000;
126 JNC clusfound
; yes, we got it ;AN000;
127 CMP DI,1 ; valid drive ,e.g. C,D... ;AN000;
128 JNZ par_found
; yes, ;AN000;
129 AND [FastSeekflg
],Fast_yes
; no more, fastseek ;AN000;
130 JMP SHORT do_norm
;AN000;
133 CALL FS_Trunc_EOF
; check EOF and truncate ;AN000;
134 JNC SKPCLP2
; redo lookup ;AN000;
136 OR [FastSeekflg
],FS_insert
; no, start to insert ;AN000;
137 CMP DX,[FSeek_logsave
] ; is current better than new? ;AN000;
138 JBE OnCache
; no, let's use new ;AN000;
139 MOV [FSeek_logclus
],DX ; use current ;AN000;
140 MOV BX,[Temp_Var2
] ; retore pysical cluster ;AN000;
141 MOV DI,BX ; insert cureent cluster ;AN000;
142 invoke FastSeek_Insert
; insert cluster # to ;AN000;
143 INC [FSeek_logclus
] ; get next inserted position ;AN000;
146 MOV CX,[FSeek_logclus
] ; get the number of clusters ;AN000;
147 SUB CX,[FSeek_logsave
] ; we need to skip ;AN000;
148 MOV DX,[FSeek_logsave
] ; cluster position ;AN000;
150 INC [FSeek_logsave
] ; get next inserted position ;AN000;
151 PUSH [FSeek_logsave
] ; logclus=logsave ;AN000;
152 POP [FSeek_logclus
] ;AN000;
159 invoke FastSeek_Insert
; insert cluster # to ;AN000;
161 PUSH BX ; FastSeek ;AN000;
168 INC [FSeek_logclus
] ; increment for next inserted ;AN000;
174 AND [FastSeekflg
],FS_no_insert
; clear insert mode
184 MOV DX,[FSeek_logclus
] ; get cluster position ;AN000;
185 MOV BX,[FSeek_logsave
] ; bx=previous cluster # PTM ;AN000;
187 MOV CX,1 ; we found it ;AN000;
192 Break <BUFSEC
-- BUFFER A SECTOR
AND SET UP A TRANSFER
>
195 ; AH = priority of buffer
196 ; AL = 0 if buffer must be read, 1 if no pre-read needed
197 ; ES:BP = Base of drive parameters
198 ; [CLUSNUM] = Physical cluster number
199 ; [SECCLUSPOS] = Sector position of transfer within cluster
200 ; [BYTCNT1] = Size of transfer
202 ; Insure specified sector is in buffer, flushing buffer before
205 ; ES:DI = Pointer to buffer
206 ; SI = Pointer to transfer address
207 ; CX = Number of bytes
209 ; [TRANS] set to indicate a transfer will occur
210 ; Carry set if error (user FAILed to I 24)
212 procedure BUFSEC
,NEAR
213 DOSAssume
CS,<DS>,"BufSec"
216 Assert ISDPB
,<ES,BP>,"BufSec"
219 MOV [ALLOWED
],allowed_FAIL
+ allowed_RETRY
+ allowed_IGNORE
223 MOV BYTE PTR [TRANS
],1 ; A transfer is taking place
230 Assert ISBUF
,<ES,DI>,"BufSec"
231 OR ES:[DI.buf_flags
],buf_isDATA
232 LEA DI,[DI].BUFINSIZ
; Point to buffer
238 Break <BUFRD
, BUFWRT
-- PERFORM BUFFERED READ
AND WRITE
>
240 ; Do a partial sector read via one of the system buffers
241 ; ES:BP Points to DPB
242 ; Carry set if error (currently user FAILed to I 24)
245 DOSAssume
CS,<DS>,"BufRd"
248 Assert ISDPB
,<ES,BP>,"BufRd"
270 Assert ISBUF
,<DS,DI>,"BufRD/EvenRD"
272 SUB SI,BX ; Position in buffer
274 Assert ISDPB
,<ES,BP>,"BufRD/EvenRD"
275 CMP SI,ES:[BP.dpb_sector_size
] ; Read Last byte?
276 JB RBUFPLACEDC
; No, leave buf where it is
277 invoke PLACEHEAD
; Make it prime candidate for chucking
278 ; even though it is MRU.
287 ; Do a partial sector write via one of the system buffers
288 ; ES:BP Points to DPB
289 ; Carry set if error (currently user FAILed to I 24)
291 procedure BUFWRT
,NEAR
292 DOSAssume
CS,<DS>,"BufWrt"
295 Assert ISDPB
,<ES,BP>,"BufWrt"
296 MOV AX,WORD PTR [SECPOS
]
297 ADD AX,1 ; Set for next sector
298 MOV WORD PTR [SECPOS
],AX ;F.C. >32mb ;AN000;
299 ADC WORD PTR [SECPOS
+2],0 ;F.C. >32mb ;AN000;
300 MOV AX,WORD PTR [SECPOS
+2] ;F.C. >32mb ;AN000;
301 CMP AX,WORD PTR [VALSEC
+2] ;F.C. >32mb ;AN000;
302 MOV AL,1 ;F.C. >32mb ;AN000;
303 JA NOREAD
;F.C. >32mb ;AN000;
304 JB doread
;F.C. >32mb ;AN000;
305 MOV AX,WORD PTR [SECPOS
] ;F.C. >32mb ;AN000;
306 CMP AX,WORD PTR [VALSEC
] ; Has sector been written before?
308 JA NOREAD
; Skip preread if SECPOS>VALSEC
324 Assert ISBUF
,<DS,BX>,"BufWrt/EvenWrt"
326 TEST [BX.buf_flags
],buf_dirty
;LB. if already dirty ;AN000;
327 JNZ yesdirty
;LB. don't increment dirty count ;AN000;
328 invoke INC_DIRTY_COUNT
;LB. ;AN000;
329 OR [BX.buf_flags
],buf_dirty
332 SUB DI,SI ; Position in buffer
336 Assert ISDPB
,<ES,BP>,"BufWrt/EvenWrt"
337 CMP SI,ES:[BP.dpb_sector_size
] ; Written last byte?
338 JB WBUFPLACED
; No, leave buf where it is
339 invoke PLACEHEAD
; Make it prime candidate for chucking
340 ; even though it is MRU.
348 Break <NEXTSEC
-- Compute next sector to read
or write
>
350 ; Compute the next sector to read or write
351 ; ES:BP Points to DPB
353 procedure NEXTSEC
,NEAR
354 DOSAssume
CS,<DS>,"NextSec"
357 Assert ISDPB
,<ES,BP>,"NextSec"
358 TEST BYTE PTR [TRANS
],-1
362 CMP AL,ES:[BP.dpb_cluster_mask
]
368 TEST [FastSeekflg
],Fast_yes
; fastseek installed? ;AN000;
369 JZ do_norm2
; no ;AN000;
370 PUSH [LASTPOS
] ; save logical cluster # ;AN000;
371 POP [FSeek_logclus
] ;AN000;
372 INC [FSeek_logclus
] ; get next cluster ;AN000;
374 TEST [FastSeekflg
],FS_begin
; from R/W ;AN000;
375 JZ do_norm2
; no ;AN000;
377 invoke FastSeek_Lookup
; call lookup ;AN000;
378 JNC clusgot
; found one ;AN000;
380 CMP DI,1 ; valid drive ,e.g. C,D... ;AN000;
381 JNZ parfound2
; yes, ;AN000;
382 AND [FastSeekflg
],Fast_yes
; no more, fastseek ;AN000;
383 JMP SHORT do_norm2
;AN000;
385 CALL FS_TRUNC_EOF
; check EOF ;AN000;
386 MOV BX,[CLUSNUM
] ; don't need partially found cluster
387 OR [FastSeekflg
],FS_insert
; prepared for cluster insertion ;AN000;
388 ; use the old bx ;AN000;
393 invoke FastSeek_Insert
; call insert ;AN000;
394 AND [FastSeekflg
],FS_no_insert
; clear insert flag ;AN000;
411 Break <OPTIMIZE
-- DO A USER DISK REQUEST WELL
>
414 ; BX = Physical cluster
415 ; CX = No. of records
416 ; DL = sector within cluster
417 ; ES:BP = Base of drives parameters
418 ; [NEXTADD] = transfer address
420 ; AX = No. of records remaining
421 ; BX = Transfer address
422 ; CX = No. or records to be transferred
423 ; DX = Physical sector address (LOW)
424 ; [HIGH_SECTOR] = Physical sector address (HIGH)
426 ; [CLUSNUM] = Last cluster accessed
428 ; Carry set if error (currently user FAILed to I 24)
429 ; ES:BP unchanged. Note that segment of transfer not set.
431 procedure OPTIMIZE
,NEAR
432 DOSAssume
CS,<DS>,"Optimize"
435 Assert ISDPB
,<ES,BP>,"Optimize"
438 MOV AL,ES:[BP.dpb_cluster_mask
]
439 INC AL ; Number of sectors per cluster
441 SUB AL,DL ; AL = Number of sectors left in first cluster
445 PUSH [LASTPOS
] ; save logical cluster # ;AN000;
446 POP [FSeek_logclus
] ;AN000;
447 INC [FSeek_logclus
] ; get next cluster ;AN000;
450 ; AL has number of sectors available in current cluster
451 ; AH has number of sectors available in next cluster
452 ; BX has current physical cluster
453 ; CX has number of sequential sectors found so far
454 ; DX has number of sectors left to transfer
455 ; ES:BP Points to DPB
456 ; ES:SI has FAT pointer
458 TEST [FastSeekflg
],Fast_yes
; fastseek installed? ;AN000;
459 JZ do_norm3
; no ;AN000;
460 TEST [FastSeekflg
],FS_begin
; from R/W ;AN000;
461 JZ do_norm3
; no ;AN000;
462 TEST [FastSeekflg
],FS_insert
; is in insert mode ? ;AN000;
463 JNZ do_norm3
; yes ;AN000;
464 invoke FastSeek_Lookup
; call lookup ;AN000;
465 JNC clusgot2
; found one ;AN000;
467 CMP DI,1 ; valid drive ,e.g. C,D... ;AN000;
468 JNZ par_found3
; yes, ;AN000;
469 AND [FastSeekflg
],Fast_yes
; no more, fastseek ;AN000;
470 JMP SHORT do_norm3
;AN000;
473 CALL FS_TRUNC_EOF
; file entry not existing ;AN000;
475 OR [FastSeekflg
],FS_insert
; prepare for insertion ;AN000;
481 invoke FastSeek_Insert
; call insert ;AN000;
482 INC [FSeek_logclus
] ; insert to next position ;AN000;
483 ;;; 11/5/86 FastSeek ;AN000;
494 MOV [CLUSNUM
],BX ; Last cluster accessed
495 SUB DX,CX ; Number of sectors still needed
498 MUL ES:[BP.dpb_sector_size
] ; Number of sectors times sector size
500 ADD AX,SI ; Adjust by size of transfer
502 POP AX ; Number of sectors still needed
503 POP DX ; Starting cluster
504 SUB BX,DX ; Number of new clusters accessed
506 POP BX ; BL = sector postion within cluster
509 AND [FastSeekflg
],FS_no_insert
; clear insert flag
515 AND [FastSeekflg
],FS_no_insert
; clear insert flag
520 SUB CX,DX ; Number of sectors in cluster we don't want
521 SUB AH,CL ; Number of sectors in cluster we accepted
522 DEC AH ; Adjust to mean position within cluster
524 MOV CX,DX ; Anyway, make the total equal to the request
528 Break <FIGREC
-- Figure sector
in allocation unit
>
531 ; DX = Physical cluster number
532 ; BL = Sector postion within cluster
533 ; ES:BP = Base of drive parameters
535 ; DX = physical sector number (LOW)
536 ; [HIGH_SECTOR] Physical sector address (HIGH)
537 ; No other registers affected.
539 procedure FIGREC
,NEAR
540 ASSUME
DS:NOTHING
,ES:NOTHING
542 Assert ISDPB
,<ES,BP>,"FigRec"
544 MOV CL,ES:[BP.dpb_cluster_shift
]
547 MOV [HIGH_SECTOR
],0 ;F.C. >32mb
549 JZ noshift
;F.C. >32mb
550 XOR CH,CH ;F.C. >32mb
554 RCL [HIGH_SECTOR
],1 ;F.C. >32mb
555 LOOP rotleft
;F.C. >32mb
560 ADD DX,ES:[BP.dpb_first_sector
]
561 ADC [HIGH_SECTOR
],0 ;F.C. >32mb
566 Break <ALLOCATE
-- Assign disk space
>
568 ;*** ALLOCATE - Allocate Disk Space
570 ; ALLOCATE is called to allocate disk clusters. The new clusters are
571 ; FAT-chained onto the end of the existing file.
573 ; The DPB contains the cluster # of the last free cluster allocated
574 ; (dpb_next_free). We start at this cluster and scan towards higher
575 ; numbered clusters, looking for the necessary free blocks.
577 ; Once again, fancy terminology gets in the way of corrct coding. When
578 ; using next_free, start scanning AT THAT POINT and not the one following it.
579 ; This fixes the boundary condition bug when only free = next_free = 2.
581 ; If we get to the end of the disk without satisfaction:
583 ; if (dpb_next_free == 2) then we've scanned the whole disk.
584 ; return (insufficient_disk_space)
586 ; dpb_next_free = 2; start scan over from the beginning.
588 ; Note that there is no multitasking interlock. There is no race when
589 ; examining the entrys in an in-core FAT block since there will be no
590 ; context switch. When UNPACK context switches while waiting for a FAT read
591 ; we are done with any in-core FAT blocks, so again there is no race. The
592 ; only special concern is that V2 and V3 MSDOS left the last allocated
593 ; cluster as "00"; marking it EOF only when the entire alloc request was
594 ; satisfied. We can't allow another activation to think this cluster is
595 ; free, so we give it a special temporary mark to show that it is, indeed,
598 ; Note that when we run out of space this algorithem will scan from
599 ; dpb_next_free to the end, then scan from cluster 2 through the end,
600 ; redundantly scanning the later part of the disk. This only happens when
601 ; we run out of space, so sue me.
603 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
604 ; C A V E A T P A T T E R S O N ;
606 ; The use of FATBYT and RESTFATBYT is somewhat mysterious. Here is the
609 ; In the NUL file case (sf_firclus currently 0) ALLOCATE is called with
610 ; entry BX = 0. What needs to be done in this case is to stuff the cluster
611 ; number of the first cluster allocated in sf_firclus when the ALLOCATE is
612 ; complete. THIS VALUE IS SAVED TEMPORARILY IN CLUSTER 0, HENCE THE CURRENT
613 ; VALUE IN CLUSTER 0 MUST BE SAVED AND RESTORED. This is a side effect of
614 ; the fact that PACK and UNPACK don't treat requests for clusters 0 and 1 as
615 ; errors. This "stuff" is done by the call to PACK which is right before
617 ; LOOP findfre ; alloc more if needed
618 ; instruction when the first cluster is allocated to the nul file. The
619 ; value is recalled from cluster 0 and stored at sf_firclus at ads4:
621 ; This method is obviously useless (because it is non-reentrant) for
622 ; multitasking, and will have to be changed. Storing the required value on
623 ; the stack is recommended. Setting sf_firclus at the PACK of cluster 0
624 ; (instead of actually doing the PACK) is BAD because it doesn't handle
625 ; problems with INT 24 well.
627 ; C A V E A T P A T T E R S O N ;
628 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
630 ; ENTRY BX = Last cluster of file (0 if null file)
631 ; CX = No. of clusters to allocate
632 ; ES:BP = Base of drive parameters
633 ; [THISSFT] = Points to SFT
635 ; EXIT 'C' set if insufficient space
636 ; [FAILERR] can be tested to see the reason for failure
637 ; CX = max. no. of clusters that could be added to file
638 ; 'C' clear if space allocated
639 ; BX = First cluster allocated
640 ; FAT is fully updated
641 ; sf_FIRCLUS field of SFT set if file was null
643 ; USES ALL but SI, BP
645 PROCEDURE ALLOCATE
,NEAR
647 DOSAssume
CS,<DS>,"Allocate"
650 Assert ISDPB
,<ES,BP>,"Allocate"
654 MOV [FATBYT
],DI ; save correct cluster 0 value
656 retc
; abort if error [INTERR?]
662 Assert ISDPB
,<ES,BP>,"Allocate/Unpack"
663 mov bx,es:[bp.dpb_next_free
]
667 ; couldn't find enough free space beyond dpb_next_free, or dpb_next_free is
668 ; <2 or >dpb_max_clus. Reset it and restart the scan
671 Assert ISDPB
,<ES,BP>,"Alloc/ads1"
672 mov es:[bp.dpb_next_free
],2
673 mov bx,1 ; Counter next instruction so first
674 ; cluster examined is 2
676 ; Scanning both forwards and backwards for a free cluster
678 ; (BX) = forwards scan pointer
679 ; (CX) = clusters remaining to be allocated
680 ; (DX) = current last cluster in file
681 ; (TOS) = last cluster of file
685 Assert ISDPB
,<ES,BP>,"Alloc/findfre"
686 CMP BX,ES:[BP.dpb_max_cluster
]
688 jmp ads7
; at end of disk
690 invoke UNPACK
; check out this cluster
691 jc ads4
; FAT error [INTERR?]
692 jnz findfre
; not free, keep on truckin
694 ; Have found a free cluster. Chain it to the file
696 ; (BX) = found free cluster #
697 ; (DX) = current last cluster in file
699 mov es:[bp.dpb_next_free
],bx ; next time start search here
700 xchg ax,dx ; save (dx) in ax
701 mov dx,1 ; mark this free guy as "1"
702 invoke PACK
; set special "temporary" mark
703 jc ads4
; FAT error [INTERR?]
704 CMP ES:[BP.dpb_free_cnt
],-1 ; Free count valid?
706 DEC ES:[BP.dpb_free_cnt
] ; Reduce free count by 1
708 xchg ax,dx ; (dx) = current last cluster in file
711 invoke PACK
; link free cluster onto file
712 ; CAVEAT.. On Nul file, first pass stuffs
713 ; cluster 0 with FIRCLUS value.
714 jc ads4
; FAT error [INTERR?]
715 xchg BX,AX ; (BX) = last one we looked at
716 mov dx,bx ; (dx) = current end of file
717 LOOP findfre
; alloc more if needed
719 ; We've successfully extended the file. Clean up and exit
721 ; (BX) = last cluster in file
724 invoke PACK
; mark last cluster EOF
726 ; Note that FAT errors jump here to clean the stack and exit. this saves us
727 ; 2 whole bytes. Hope its worth it...
730 ; calling (BX) and (CX) pushed on stack
733 POP CX ; Don't need this stuff since we're successful
735 invoke UNPACK
; Get first cluster allocated for return
736 ; CAVEAT... In nul file case, UNPACKs cluster 0.
738 invoke RESTFATBYT
; Restore correct cluster 0 value
740 XCHG BX,DI ; (DI) = last cluster in file upon our entry
742 retnz
; we were extending an existing file
744 ; We were doing the first allocation for a new file. Update the SFT cluster
746 ;; Extended Attributes
747 ; TEST [XA_condition],XA_No_SFT ;FT. don't update SFT when from ;AN000;
748 ; JZ dofastk ;FT. GetSet_XA ;AN000;
749 ; AND [XA_condition],not XA_No_SFT ;FT. clear the bit ;AN000;
755 MOV DL,ES:[BP.dpb_drive
] ; get drive #
759 Assert ISSFT
,<ES,DI>,"Allocate/ads4"
760 MOV ES:[DI.sf_firclus
],BX
761 MOV ES:[DI.sf_lstclus
],BX
763 TEST [FastSeekflg
],Fast_yes
; fastseek installed
765 TEST [FastSeekflg
],FS_begin
; do fastseek
768 MOV CX,BX ; set up firclus #
769 MOV [FSeek_firclus
],BX ; update firclus varible
770 invoke FastSeek_Open
; create this file entry
779 ;** we're at the end of the disk, and not satisfied. See if we've scanned ALL
782 ads7: cmp es:[bp.dpb_next_free
],2
785 jmp ads1
; start scan from front of disk
793 ; Sorry, we've gone over the whole disk, with insufficient luck. Lets give
794 ; the space back to the free list and tell the caller how much he could have
795 ; had. We have to make sure we remove the "special mark" we put on the last
796 ; cluster we were able to allocate, so it doesn't become orphaned.
798 ; (CX) = clusters remaining to be allocated
799 ; (TOS) = last cluster of file (before call to ALLOCATE)
800 ; (TOS+1) = # of clusters wanted to allocate
803 POP BX ; (BX) = last cluster of file
805 invoke RELBLKS
; give back any clusters just alloced
806 POP AX ; No. of clusters requested
807 ; Don't "retc". We are setting Carry anyway,
808 ; Alloc failed, so proceed with return CX
810 SUB AX,CX ; AX=No. of clusters allocated
811 invoke RESTFATBYT
; Don't "retc". We are setting Carry anyway,
813 ; fmt <>,<>,<"$p: disk full in allocate\n">
814 MOV [DISK_FULL
],1 ;MS. indicating disk full
820 ; SEE ALLOCATE CAVEAT
821 ; Carry set if error (currently user FAILed to I 24)
823 procedure RESTFATBYT
,NEAR
824 DOSAssume
CS,<DS>,"RestFATByt"
839 Break <RELEASE
-- DEASSIGN DISK SPACE
>
842 ; BX = Cluster in file
843 ; ES:BP = Base of drive parameters
845 ; Frees cluster chain starting with [BX]
846 ; Carry set if error (currently user FAILed to I 24)
847 ; AX,BX,DX,DI all destroyed. Other registers unchanged.
849 procedure RELEASE
,NEAR
850 DOSAssume
CS,<DS>,"Release"
855 DOSAssume
CS,<DS>,"RelBlks"
856 Assert ISDPB
,<ES,BP>,"RelBlks"
858 ; Enter here with DX=0FFFFH to put an end-of-file mark in the first cluster
859 ; and free the rest in the chain.
870 JNZ NO_DEALLOC
; Was putting EOF mark
871 CMP ES:[BP.dpb_free_cnt
],-1 ; Free count valid?
873 INC ES:[BP.dpb_free_cnt
] ; Increase free count by 1
876 dec ax ; check for "1"
877 retz
; is last cluster of incomplete chain
879 JB RELEASE
; Carry clear if JMP not taken
883 Break <GETEOF
-- Find the
end of a
file>
886 ; ES:BP Points to DPB
887 ; BX = Cluster in a file
890 ; BX = Last cluster in the file
891 ; Carry set if error (currently user FAILed to I 24)
892 ; DI destroyed. No other registers affected.
894 procedure GETEOF
,NEAR
895 DOSAssume
CS,<DS>,"GetEOF"
898 Assert ISDPB
,<ES,BP>,"GetEof"
905 JAE RET12
; Carry clear if jmp
910 Break <FS_TRUNC_EOF
- truncate EOF for Fastseek
>
913 ; ES:BP Points to DPB
914 ; BX = Cluster in a file
915 ; Functions: if BX=EOF then truncate it from Fastseek Cache
918 ; carry clear: EOF and do truncate
920 procedure FS_TRUNC_EOF
,NEAR
921 ASSUME
ES:NOTHING
,DS:NOTHING
923 MOV BX,DI ; get beginning physical# ;AN000;
924 invoke IsEOF
; is EOF ;AN000;
925 JB noteof2
; no ;AN000;
926 PUSH [FSeek_logclus
] ; ;AN000;
927 PUSH [FSeek_logsave
] ; logclus=logsave ;AN000;
928 POP [FSeek_logclus
] ; delete EOF ;AN000;
929 invoke FastSeek_Truncate
; ;AN000;
930 POP [FSeek_logclus
] ; redo the look up ;AN000;
934 EndProc FS_TRUNC_EOF
;AN000;