mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-25 09:30:50 +00:00
357 lines
14 KiB
Plaintext
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
|
||
|
|