boot3/OS/HFS/TFSCOMMON.a
Elliot Nunn 5b0f0cc134 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 10:02:57 +08:00

357 lines
14 KiB
Plaintext

;
; File: TFSCOMMON.a
;
; Contains: This file contains common utility routines
;
; Copyright: © 1985-1991, 1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM3> 8/3/93 BH Changed MarkVCB and FlushMDB to keep an eye on the
; vcbFlushCritBit flag for manual-eject drives.
; <2> 9/12/91 JSM Add a header.
; <1.2> 3/2/89 DNF removed references to forROM; HFS now builds identically for ram
; or rom
; <1.1> 11/10/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; <1.0> 2/11/88 BBM Adding file for the first time into EASEÉ
; 2/19/87 BB Vectored FlushMDB.
; 11/20/85 BB FlushMDB now clears FCB dirty flag for the Extents and Catalog
; file FCBs. (ROM75 patch).
; 11/6/85 PWD Changed RoundAlloc to call DivUp by BSR.S **** changes since
; ROM75 release ****
; 10/20/85 LAK Preserve D0 in MarkVCBDirty debug code (CVFlgs was trashing it).
; 10/16/85 PWD Changed FlushMDB to not set LsMod time on dirty VCBs.
; 10/10/85 LAK Added routine MarkVCBDirty to mark VCB dirty without changing
; its mod date (special for eject).
; 10/1/85 LAK Modified GetVCBDrv to look for OffLine and Ejected volumes.
; 9/22/85 PWD Changed FlushMDB to update VCBXTAlBks and VCBCTAlBks in VCB from
; FCB information
; 8/22/85 PWD Added RoundAlloc.
; 7/11/85 PWD New today
;
;_______________________________________________________________________
;
; External Routines: DivUp,RoundAlloc,FlushMDB
;
; Internal Routines:
;
; Called By: FlushVol,XFFlush,CMFlush
;
;_______________________________________________________________________
;_______________________________________________________________________
;
; DivUp subroutine: compute the minimum number of allocation blocks necessary
; to store a given number of bytes (a division followed by
; a round-up).
;
; Inputs:
; D0.L - Byte length of run on disk
; D1.W - Allocation block size
;
; Outputs:
; D0.L - Number of allocation blocks required (top word is zeroed)
;_______________________________________________________________________
;
BLANKS ON
STRING ASIS
DivUp: DIVU D1,D0 ; Divide by allocation blocks size
SWAP D0 ; Examine the remainder
TST.W D0 ;
BEQ.S @10 ; If zero, we have a perfect fit.
CLR.W D0 ; If not, clear the remainder
SWAP D0 ; Restore the quotient
ADDQ.W #1,D0 ; and add one
BRA.S @20 ;
@10: SWAP D0 ; Restore quotient to lower word
@20: RTS ; And call it a day.
;_______________________________________________________________________
;
; RoundAlloc: Compute the size in bytes of a byte length in allocation
; blocks, rounded up to a given clump-size boundary.
;
; Inputs:
; D0.L - Size in bytes
; D1.L - Clump size in bytes (must be 512 multiple)
; A2.L - VCB pointer (for AlBlkSiz)
;
; Outputs:
; D0.L - Rounded size in allocation blocks (always 16 bits, top word clear)
;_______________________________________________________________________
;
RoundAlloc:
MOVE.L D1,-(SP) ; Save across call
MOVE.L D0,-(SP) ; Save original byte length
MOVE.L D1,D0 ; Set up to compute ClpSiz in AlBlks
MOVE.L VCBAlBlkSiz(A2),D1 ; Pick up allocation block size in bytes
BSR.S DivUp ; Divide, yielding ClpSize in AlBlks <06Nov85>
MOVE.L D0,D1 ; Stash away temporarily
MOVE.L (SP)+,D0 ; Now then, let's get to work
MOVE.L D1,-(SP) ; Move this divisor out of the way
MOVE.L VCBAlBlkSiz(A2),D1 ; Pick up alloc. block size again
BSR.S DivUp ; Divide, yielding length in AlBlks <06Nov85>
MOVE.L (SP)+,D1 ; Recover clump size in AlBlks again
BSR.S DivUp ; Get size in Clumps <06Nov85>
MULU D1,D0 ; And mult. back out -> size in AlBlks
; (guaranteed to be word magnitude)
*PWD* MOVE.L VCBAlBlkSiz(A2),D1 ; Pick up alloc. block size again
*PWD* MULU D1,D0 ; Get size in bytes again
MOVE.L (SP)+,D1 ; Recover original D1
RTS
;_______________________________________________________________________
;
; Routine: QWordSearch
; Arguments: A0.L (input) -- pointer to queue header
; D0.W (input) -- word parameter to look for
; D1.W (input) -- field offset for compare
; A0.L (output) -- pointer to queue element which matched
; D0.W (output) -- 0=success, -1=failure
; D1, other regs are preserved
; Called By: FindDrive,GetVCBDrv,GetVCBRfn
; Function: General queue search routine.
;
; Modification History:
; 06 Dec 82 LAK New today.
;_______________________________________________________________________
QWordSearch:
MOVE.L D2,-(SP) ; save D2
MOVE.L QHead(A0),D2 ; get first element
@1 BEQ.S @4 ; exit if no match
MOVE.L D2,A0 ; next element pointer
CMP.W 0(A0,D1),D0 ; match?
BEQ.S @2 ; then take the good exit . . .
MOVE.L QLink(A0),D2
BRA.S @1
@2 MOVEQ #0,D0
@3 MOVE.L (SP)+,D2 ; restore D2
TST.W D0
RTS
@4 MOVEQ #-1,D0
BRA.S @3
;_______________________________________________________________________
;
; Routine: GetVCBRfn,GetVCBDrv,GetWDCBRfn
; Arguments: D0.W (input) -- IODrvNum(A0) = IOVRefNum(A0) (for VCB or WD)
; D0.W (output) -- error code (no such volume) or 0
; A2.L (output) -- VCB pointer or WDCB pointer
; All other regs are preserved
; Calls: QWordSearch
; Called By: DtrmV3,MountVol(make sure no volume already mounted on a drive)
; Function: Determine VCB from DriveNum/VRefNum field.
;
; Modification History:
; 01 Jun 83 LAK New today.
; 22 Feb 85 GJC Added support for WDCB search (GetWDCBRfn).
; 28-Feb-85 PWD Changed GetWDCBRfn to store WDCB pointer in A3.
; 14-Mar-85 PWD Changed WDCB search algorithm to mimick FCB logic; WDCB's are
; allocated from a pre-allocated array a la FCBs.
; 23-Feb-85 PWD Fixed bug in GetWDCBRfn resulting from (A3)+ on CMP to D0
; 1-May-85 PWD Added WDVCBPtr check to GetWDCBRfn.
; <01Oct85> LAK Modified GetVCBDrv to look for OffLine volumes.
; <16Oct85> PWD Changed FlushMDB to not set LsMod time on dirty VCBs
;_______________________________________________________________________
GetVCBRfn:
MOVEM.L D1/A0,-(SP) ; save regs
MOVEQ #VCBVRefNum,D1
LEA VCBQHdr,A0 ; search the queue of VCBs
BSR.S QWordSearch
BNE.S @2
MOVE.L A0,A2 ; return VCB ptr in A2
@1 MOVEM.L (SP)+,D1/A0
RTS
@2 MOVEQ #NSVErr,D0 ; no such volume
BRA.S @1
GetVCBDrv:
MOVEM.L D1-D2,-(SP) ; save regs other than A2/D0 <01Oct85>
MOVE.W D0,D1 ; save drive parameter in D1 <01Oct85>
MOVE.W D0,D2 ; save negated value in D2 for <01Oct85>
NEG.W D2 ; offline volume check <01Oct85>
MOVE.L VCBQHdr+QHead,A2 ; get first VCB ptr
@1 MOVE.L A2,D0 ; see if it's there
BEQ.S @5 ; fail <01Oct85>
CMP.W VCBDrvNum(A2),D1 ; this one? <01Oct85>
BEQ.S @3 ; br if so <01Oct85>
TST.W VCBDrvNum(A2) ; offline? <01Oct85>
BNE.S @2 ; br if not <01Oct85>
CMP.W VCBDRefNum(A2),D2 ; match? <01Oct85>
BEQ.S @3 ; br if found <01Oct85>
@2 MOVE.L QLink(A2),A2 ; go to next VCB <01Oct85>
BRA.S @1 ; <01Oct85>
@3 MOVEQ #0,D0 ; success! <01Oct85>
@4 MOVEM.L (SP)+,D1-D2 ; restore regs <01Oct85>
RTS ; <01Oct85>
@5 MOVEQ #NSVErr,D0 ; no such volume <01Oct85>
BRA.S @4 ; <01Oct85>
; Set up A3->WDCB, A2->VCB, D0=0
; If error, D0=NSVErr or RFNumErr . . .
GetWDCBRfn MOVEA.L WDCBsPtr,A3 ; Point to WDCB array
MOVEM.L A1/D1,-(SP) ; Save A1/D1 away for use as scratch
MOVEQ #0,D1 ; Clear top half of D1
MOVE.W D0,D1 ; Set up for check
BSR CkWDRefNum ; Use check subroutine . (sets D0, blows A1) <29Aug85>
BNE.S @1 ; Br if error <29Aug85>
SUB.W #WDRfnMin,D1 ; Offset to form index into WDCB array
ADDA.W D1,A3 ; Offset to point to WDCB
MOVEQ #NSVErr,D0 ; Expect the worst
MOVE.L WDVCBPtr(A3),D1 ; Pick up the VCB pointer
BEQ.S @1 ; If clear, this WDCB was actually unused
MOVEA.L D1,A2 ; Otherwise, this is a fine VCB pointer
MOVEQ #0,D0 ; Indicate success
@1 MOVEM.L (SP)+,A1/D1 ; Restore A1/D1 <29Aug85>
TST.W D0 ; Set CCR <29Aug85>
RTS ; <29Aug85>
;_______________________________________;
;
; MarkVCB utility... ;
;_______________________________________;
MarkVCB:
BSR.S MarkVCBDirty ; Mark the VCB dirty <18Oct85>
MarkVCBTime:
MOVE.L Time,VCBLsMod(A2) ; Set the time of death
IF hasManEject THEN ; the mod date is critical volume info, used to identify a volume in a remount
; we need to update this change to the disk ASAP if it is in a manual-eject drive,
; since it may be removed at any time and we need to be able to tell if it is remounted
; <SM3> <BH 03Aug93>
MOVE.L D0,-(SP) ; save D0 <SM3> <BH 03Aug93>
MOVE.W vcbFlags(A2),D0 ; <SM3> <BH 03Aug93>
BTST #vcbManEjBit,D0 ; volume in a manual-eject drive? <SM3> <BH 03Aug93>
BEQ.S @noflush ; no, skip this <SM3> <BH 03Aug93>
BSET #vcbFlushCritBit,D0 ; signal need to flush the critical info <SM3> <BH 03Aug93>
MOVE.W D0,vcbFlags(A2) ; <SM3> <BH 03Aug93>
@noflush MOVE.L (SP)+,D0 ; restore D0 <SM3> <BH 03Aug93>
ENDIF ; <SM3> <BH 03Aug93>
RTS ; And return to more important things
MarkVCBDirty
IF HFSDebug THEN
MOVE.L D0,-(SP) ; Preserve D0 <20Oct85>
BSR CVFlgs ; Can we actually write this volume? <18Oct85>
BEQ.S @1 ; Yes. <18Oct85>
_HFSDebug $127 ; No - this MDB cannot be flushed... and you<18Oct85>
; may say to yourself "How did I get here?" <18Oct85>
@1 MOVE.L (SP)+,D0 ; Restore D0 <20Oct85>
ENDIF
ST VCBFlags(A2) ; Mark the VCB dirty (special for eject) <10Oct85>
RTS ; <10Oct85>
FlushMDB:
MOVE.L jFlushMDB,-(SP) ; jump table entry for vFlushMDB <19Feb87>
RTS ; go there <19Feb87>
vFlushMDB ; 'vectored' FlushMDB routine <19Feb87>
MOVE.L (SP)+,-(A6) ; Save return address across ,ASYNC calls
MOVEM.L D0-D2/A0-A1,-(A6) ; Save scratch registers
; Write out the MDB, if dirty:
IF HFSDebug THEN ; *** ONLY INCLUDE WHEN DEBUGGING ***
TST.W VCBDRVNUM(A2) ; Make sure the volume's on-line.
BNE.S @1
DC.W $FAAA
@1
ENDIF
TST.B VCBFlags(A2) ; VCB Dirty?
BPL FlMDBExit ; If not, don't bother writing it out
MOVEA.L VCBBufAdr(A2),A1 ; Point to volume cache queue header
MOVE.W VCBVRefNum(A2),D0 ; Volume refNum
MOVEQ #0,D1 ; Clear flag byte
; *PWD*: Read in a fresh copy of the MDB to allow other programs to write the
; last half of the MDB and not be clobbered by our writing of the MDB:
; *LAK*: Not such a good idea. Other programs should leave our MDB alone. Let them
; use the last block on disk if they must (we don't touch it).
MOVEQ #2,D2 ; MDB is block 2 (third block on disk)
JSR GetBlock ; Point A0 to cache buffer
BNE FlMDBExit ; Punt on errors
MOVEA.L A0,A1 ; Set up as destination for _BlockMoves
LEA VCBDInfoSt(A2),A0 ; Point to MDB info in VCB
MOVE.L #LenMDB,D0 ; Length to copy
_BlockMove ; Copy VCB info
; Add some TFS-specific information:
LEA VCBTDInfoSt(A2),A0 ; Point to additional info
LEA DrTInfoSt(A1),A1 ; Point to tail end of MDB
MOVEQ #VCBTDILen,D0 ; Length of TFS info
_BlockMove ; Copy it into the MDB Buffer
SUBA.L #DrTInfoSt,A1 ; Point A1 back to start of buffer
MOVEA.L FCBsPtr,A3 ; Point to FCB array
MOVE.W VCBXTRef(A2),D1 ; Get extent file refNum
MOVEM.L A0-A1,-(SP) ; Free up some scratch registers
MOVEQ #lenXDR,D0 ; Length of extent record
LEA FCBExtRec(A3,D1),A0 ; Point to extent record in FCB
LEA DrXTExtRec(A1),A1 ; Point to first (and only) XT extent record
_BlockMove ; Copy in the extent record
MOVEM.L (SP)+,A0-A1 ; Restore originals
MOVE.L FCBPLen(A3,D1.W),D0 ; Pick up length of extent B*-Tree <22Sep85>
MOVE.L D0,DrXTFlSize(A1) ; Store length of extent tree in MDB buffer <22Sep85>
BCLR #FCBModBit,FCBMdRByt(A3,D1.W) ; clear the FCB dirty flag <20Nov85>
MOVE.L VCBAlBlkSiz(A2),D1 ; Pick up volume's allocation block size <22Sep85>
JSR DivUp ; Compute extent B*-Tree size in AlBlks <22Sep85>
MOVE.W D0,VCBXTAlBks(A2) ; And save it for posterity <22Sep85>
MOVE.W VCBCTRef(A2),D1 ; Get catalog file RefNum
MOVEM.L A0-A1,-(SP) ; Free up some scratch registers (again)
MOVEQ #lenXDR,D0 ; Length of extent record
LEA FCBExtRec(A3,D1),A0 ; Point to extent record in FCB
LEA DrCTExtRec(A1),A1 ; Point to first (and only) XT extent record
_BlockMove ; Copy in the extent record
MOVEM.L (SP)+,A0-A1 ; Restore originals
MOVE.L FCBPLen(A3,D1.W),D0 ; Pick up length of catalog B*-Tree <22Sep85>
MOVE.L D0,DRCTFlSize(A1) ; Store length of catalog tree <22Sep85>
BCLR #FCBModBit,FCBMdRByt(A3,D1.W) ; clear the FCB dirty flag <20Nov85>
MOVE.L VCBAlBlkSiz(A2),D1 ; Pick up volume's allocation block size <22Sep85>
JSR DivUp ; Compute allocation in alloc. blocks <22Sep85>
MOVE.W D0,VCBCTAlBks(A2) ; And save the result for posterity <22Sep85>
; Write the MDB out by releasing the block dirty
MOVEQ #kRBWrite,D1 ; Force it to be written . . . <01Oct85>
MOVEA.L A1,A0 ; Point to MDB buffer
MOVEA.L VCBBufAdr(A2),A1 ; Point to volume Cache Queue Header
JSR RelBlock ; Release the cache block
IF hasManEject THEN ; the critical volume info that needs to be maintained <SM3> <BH 03Aug93>
; for volumes in manual-eject drives has been flushed. <SM3> <BH 03Aug93>
BNE.S FlMDBExit ; don't clear either dirty bit if an error occurred <SM3> <BH 03Aug93>
MOVE.W vcbFlags(A2),D0 ; do this properly...get the whole flags word <SM3> <BH 03Aug93>
BCLR #vcbFlushCritBit,D0 ; clear the correct bit <SM3> <BH 03Aug93>
MOVE.W D0,vcbFlags(A2) ; and restore the flags <SM3> <BH 03Aug93>
ENDIF; v--------------------------note naughty alternate flag-clearing method here. <SM3> <BH 03Aug93>
CLR.B VCBFlags(A2) ; VCB is not dirty any longer . . . <28Aug85>
FlMDBExit MOVEM.L (A6)+,D0-D2/A0-A1 ; Restore scratch registers
MOVE.L (A6)+,-(A7) ; Restore return address
TST.W D0
RTS