mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-22 19:31:02 +00:00
715 lines
29 KiB
Plaintext
715 lines
29 KiB
Plaintext
;
|
|
; File: VSM.a
|
|
;
|
|
; Contains: This module provides the Volume Space Management in the Turbo
|
|
; File System.
|
|
;
|
|
; Written by: Patrick W. Dirks, December 11 1984
|
|
;
|
|
; Copyright: © 1984-1991 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <2> 9/13/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.1> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles
|
|
; <1.0> 2/11/88 BBM Adding file for the first time into EASE…
|
|
; 10/27/86 BB Vectored ReadBM routine.
|
|
; 9/25/86 BB Updated to use new MPW equate files.
|
|
; 10/29/85 LAK Vectored BlkAlloc, BlkDealloc.
|
|
; 10/25/85 PWD Fixed FrBitScn to back up starting position before backing out
|
|
; at EOV. Added debugging code to catch partial-word $FFFF
|
|
; advances.
|
|
; 10/24/85 PWD Added debugging code to check allocation before return
|
|
; 10/22/85 PWD Fixed bug in EOV check in FrBitScan
|
|
; 10/21/85 PWD Changed BlkAlloc to check VCBFreeBks before attempting to
|
|
; allocate any block. Speed up scan for free space by checking for
|
|
; all 1's.
|
|
; 10/6/85 PWD Changed to return error instead of calling _SysError Changed to
|
|
; call common subroutine NextBit
|
|
; 10/1/85 LAK Use GBrelease option when calling GetBlock.
|
|
; 9/8/85 LAK Added routine UpdateFree to refigure the free block count for
|
|
; the MountVol consistency check.
|
|
; 9/3/85 LAK Contiguous allocation had a bug with buffer non-release. Rewrote
|
|
; this to use MarkBlock to dirty a block instead, and immediately
|
|
; call RelBlock after GetBlock.
|
|
; 8/21/85 PWD Fixed request size rounding to pre-divide by VCBAlBlSiz.
|
|
; 7/3/85 PWD Added consistency checking code.
|
|
; 5/28/85 PWD Changed to leave AllocPtr at start of last allocation (to
|
|
; minimize fragmentation after truncate on Close).
|
|
; 5/13/85 PWD Added code to BlkAlloc to check for zero free space
|
|
; 3/22/85 PWD Changed to use A6 stack, and use word-sized AlBlkSize
|
|
; 2/24/85 PWD Added explicit TST.W D0 in routines to re-set status codes
|
|
; 2/12/85 PWD Changed BlkDealloc to pass on result code in D0
|
|
; 2/11/85 PWD Changed BlkDealloc to check for zero-length block counts.
|
|
; 12/11/84 PWD New today.
|
|
;
|
|
|
|
;________________________________________________________________________________
|
|
;
|
|
; Routines: BlkAlloc, BlkDealloc, BlkChk
|
|
;
|
|
;________________________________________________________________________________
|
|
|
|
|
|
BLANKS ON
|
|
STRING ASIS
|
|
|
|
PRINT OFF
|
|
LOAD 'StandardEqu.d'
|
|
PRINT ON
|
|
PRINT NOGEN
|
|
|
|
VSM PROC EXPORT
|
|
|
|
EXPORT BlkAlloc, BlkDealloc, BlkChk, UpdateFree
|
|
IMPORT GetBlock,RelBlock,MarkBlock,DivUp,RoundAlloc,MarkVCB
|
|
|
|
EXPORT vBlkAlloc,vBlkDealloc,vReadBM ;<27Oct86>
|
|
|
|
EJECT
|
|
;________________________________________________________________________________
|
|
;
|
|
; Routine: BlkAlloc
|
|
;
|
|
; Function: Allocate space on a volume. If contiguous allocation is requested,
|
|
; at least the requested number of bytes will be allocated or an
|
|
; error will be returned. If contiguous allocation is not forced,
|
|
; the space will be allocated at the first free fragment following
|
|
; the requested starting allocation block. If there is not enough
|
|
; room there, a block of less than the requested size will be
|
|
; allocated.
|
|
;
|
|
; If the requested starting block is 0 (for new file allocations),
|
|
; the volume's allocation block pointer will be used as a starting
|
|
; point.
|
|
;
|
|
; All requests will be rounded up to the next highest clump size, as
|
|
; indicated in the file's FCB.
|
|
;
|
|
; Input Arguments:
|
|
; A2 - Pointer to VCB for the volume to allocate space on
|
|
; A3 - Pointer to FCB for the file for which storage is being allocated
|
|
; D2.W - Preferred starting allocation block, 0 = no preference
|
|
; D3.B - Force contiguous flag - if bit 0 set (NE), allocation is contiguous
|
|
; or an error is returned
|
|
; D4.L - Number of bytes requested. If the allocation is non-contiguous, less
|
|
; than this may actually be allocated
|
|
;
|
|
; Output:
|
|
; D0.W - Error code, zero for successful allocation
|
|
; D2.W - Actual starting allocation block
|
|
; D3.W - Actual number of allocation blocks allocated
|
|
;
|
|
; Internal register usage:
|
|
; A0 - Pointed to bitmap buffer
|
|
; A1.W - Used to hold the number of allocation blocks on the volume
|
|
; D0.W - Used to hold current bitmap word
|
|
; D1.W - Count of number of unexamined bits left in D0
|
|
; D3.L - High word used to stash starting allocation block
|
|
; D5.W - Current bitmap block number
|
|
; D6.W - Index into bitmap block buffer
|
|
; D7.W - Number of allocation blocks actually allocated
|
|
;
|
|
; Side effects:
|
|
; The volume bitmap is read and updated; the volume bitmap cache may be changed.
|
|
;
|
|
; Modification history:
|
|
; <06Oct85> PWD Changed to check for errors after calls to ReadBM and NextWord
|
|
; Relocated call to MarkBlock in allocation loop
|
|
; Changed to call NextBit
|
|
; <21Oct85> PWD Changed to check VCBFreeBks before attempting to allocate any block.
|
|
; Speed up scan for free space by checking for all 1's.
|
|
;________________________________________________________________________________
|
|
;
|
|
|
|
BlkAlloc:
|
|
MOVE.L jBlkAlloc,-(SP) ; jumptable entry for vBlkAlloc <29Oct85>
|
|
RTS ; go there <29Oct85>
|
|
vBlkAlloc ; 'vectored' BlkAlloc routine <29Oct85>
|
|
|
|
MOVE.L (SP)+,-(A6) ; Save return address
|
|
MOVEM.L D1/D4-D7/A0-A1,-(A6); Save caller's registers
|
|
TST.W VCBFreeBks(A2) ; Any blocks free at all?
|
|
BEQ bkAllocFull ; Exit if not <03Sep85>
|
|
|
|
ANDI.W #$0001,D3 ; Clear all extra bits for our use
|
|
TST.W D2 ; Preferred starting block selected?
|
|
BNE.S @1 ; Yes - leave it be.
|
|
MOVE.W VCBAllocPtr(A2),D2 ; No - start from the volume-wide pointer
|
|
BSET #7,D3 ; Set flag to update vcbAllocPtr later
|
|
|
|
@1: SWAP D3 ; Get high word accessible
|
|
MOVE.W D2,D3 ; Store starting block
|
|
SWAP D3 ; And restore flags word for use
|
|
BCLR #15,D3 ; Clear wrap-around flag
|
|
|
|
blkLoop:
|
|
BSR ReadBM ; Pick up the bitmap block of interest
|
|
TST.W D1 ; No errors? <PWD 06Oct85>
|
|
BMI bkAllocExit ; If negative, D0 is now error code <PWD 06Oct85>
|
|
|
|
MOVEA.W VCBNmAlBlks(A2),A1 ; Set up the size of the volume
|
|
|
|
; Look for a free fragment at or beyond the starting block selected:
|
|
|
|
@1: CMP.W A1,D2 ; Did we reach the end-of-volume?
|
|
BCS.S @2 ; If not (D2 < A1), march merrily along
|
|
|
|
ROL.L D1,D0 ; Rotate D0 back into place
|
|
MOVE.L D0,0(A0,D6.W) ; Replace it in the buffer (buffer is clean)
|
|
CLR.W D2 ; Reset the starting block to the beginning
|
|
BSR ReadBM ; Read the appropriate bitmap block
|
|
BSET #15,D3 ; Indicate we wrapped around the EOV
|
|
BNE bkAllocFull ; Exit if already set, with DskFulErr, D3=0
|
|
|
|
; It wasn't set yet, start over again
|
|
|
|
@2: TST.W D1 ; Any errors occur? <PWD 06Oct85>
|
|
BMI bkAllocExit ; Punt on errors <PWD 06Oct85>
|
|
TST.L D0 ; If bit 31 clear (free alloc. block)?
|
|
BPL.S bkAlFree ; If so, check if fragment is big enough
|
|
BSR FrBitScan ; Look for another free bit. <PWD 21Oct85>
|
|
BRA.S @1 ; And keep trying
|
|
|
|
; We found a free fragment; check to see if it isn't too small. For a contiguous
|
|
; allocation, this should guarantee that at least as much as requested is actually
|
|
; allocated, although more may be granted; the request is rounded up to the next
|
|
; highest clump later.
|
|
|
|
bkAlFree:
|
|
SUB.W D2,A1 ; Change A1 to # block left to EOV
|
|
BTST #0,D3 ; Is contiguous allocation requested?
|
|
BEQ.S bkAllocDoIt ; If not, just start allocating here.
|
|
|
|
MOVE.L D4,-(A6) ; Store original alloc. request size
|
|
|
|
MOVEM.L D0-D1,-(A6) ; Free up for use in division
|
|
MOVE.L D4,D0 ; Set up to divide
|
|
MOVE.W vcbAlBlkSiz+2(A2),D1 ; by allocation block size
|
|
JSR DivUp ; and round result up to next alloc. block
|
|
MOVE.L D0,D4 ; D4 is now min. number of alloc. blocks
|
|
MOVEM.L (A6)+,D0-D1 ; Restore original registers
|
|
CLR.W D7 ; Set up fragment length count, al. blocks
|
|
|
|
@1: CMP.W D7,D4 ; Check current length: enough already?
|
|
BLS.S @5 ; If reguest <= fragment so far, go for it!
|
|
CMP.W A1,D7 ; Reached the edge?
|
|
BEQ.S @2 ; If so, that wasn't quite enough
|
|
TST.L D0 ; If bit 31 set (allocated block)?
|
|
BMI.S @2 ; If so, fragment wasn't big enough
|
|
ADDQ.W #1,D7 ; If not, bump fragment length count
|
|
BSR NextBit ; Pick up the next bit out of the bitmap <PWD 06Oct85>
|
|
TST.W D1 ; Any errors occur? <PWD 06Oct85>
|
|
BMI bkAllocExit ; Punt on errors <PWD 06Oct85>
|
|
BRA.S @1 ; Otherwise keep trying
|
|
|
|
@2: MOVE.L (A6)+,D4 ; Restore original request size (bytes)
|
|
ADD.W D7,D2 ; This fragment too small - update starting block
|
|
CMP.W A1,D7 ; Did we reach to the EOV?
|
|
BCS.S @3 ; Nope - try this for a next position
|
|
BTST #15,D3 ; Did we wrap around yet?
|
|
BNE.S @4 ; Yes - give up: history repeats itself
|
|
BSET #15,D3 ; No - give it another shot
|
|
CLR.W D2 ; From the beginning of the volume
|
|
|
|
@3: BTST #15,D3 ; Did we wrap around yet?
|
|
BEQ blkLoop ; If not, scan on
|
|
|
|
SWAP D3 ; Get a hold of the starting block
|
|
CMP.W D2,D3 ; Are we back where we started?
|
|
BLS.S @4 ; If we're beyond the start, quit
|
|
SWAP D3 ; Otherwise, restore D3
|
|
BRA blkLoop ; And scan on
|
|
|
|
@4: ROL.L D1,D0 ; Rotate D0 back into place
|
|
MOVE.L D0,0(A0,D6.W) ; And replace it in the buffer
|
|
BRA bkAllocFull ; Exit with DskFulErr, D3=0 <03Sep85>
|
|
|
|
@5: MOVE.L (A6)+,D4 ; Retrieve request size in bytes
|
|
ROL.L D1,D0 ; Restore D0 to its original position ???
|
|
MOVE.L D0,0(A0,D6.W) ; Replace it in the buffer (buffer is still clean) ???
|
|
BSR ReadBM ; And set up from the current position (D2)
|
|
TST.W D1 ; Any errors occur? <PWD 06Oct85>
|
|
BMI bkAllocExit ; Punt on errors <PWD 06Oct85>
|
|
|
|
; Start allocating block at this point: round the request off to the next highest
|
|
; clump size now, and try to take as much as possible up to that limit.
|
|
|
|
bkAllocDoIt:
|
|
MOVEM.L D0-D1,-(A6) ; Save current bitmap word & bit count
|
|
MOVE.L D4,D0 ; Get requested allocation length (bytes) <22Aug85>
|
|
MOVE.L FCBClmpSize(A3),D1 ; Get clump size for file <22Aug85>
|
|
JSR RoundAlloc ; Divide, rounding up -> Size in AlBlks <22Aug85>
|
|
MOVE.L D0,D4 ; Stash it away <22Aug85>
|
|
MOVEM.L (A6)+,D0-D1 ; And retrieve original bitmap word & count
|
|
CLR.L D7 ; Zero out actual allocation counter
|
|
|
|
; Mark blocks allocated from the starting block:
|
|
|
|
@1: TST.W D4 ; Allocated enough already?
|
|
BEQ.S BkAllocOK ; If so, quit
|
|
CMP.W A1,D7 ; If not, is there more here?
|
|
BCC.S BkAllocOK ; If D7 >= A1, we've reached the EOV
|
|
TST.L D0 ; Check bit 31 of current word (curr. blk)
|
|
BMI.S BkAllocOK ; If allocated, stop trying
|
|
|
|
TST.W VCBFreeBks(A2) ; Does vol. think there are any bits left? <PWD 21Oct85>
|
|
BEQ.S BkAllocOK ; Nope - we're done (for) then . . . <PWD 21Oct85>
|
|
SUBQ.W #1,VCBFreeBks(A2) ; Yes - well, there's one fewer now. <PWD 21Oct85>
|
|
JSR MarkVCB ; Mark the VCB dirty <PWD 21Oct85>
|
|
|
|
BSET #31,D0 ; Mark the current block as allocated
|
|
ADDQ.W #1,D7 ; Add one to allocated block count
|
|
SUBQ.W #1,D4 ; Subtract one from request size
|
|
JSR MarkBlock ; This block is dirty . . . <PWD 06Oct85>
|
|
BSR NextBit ; Get the next bit from the bitmap <PWD 06Oct85>
|
|
TST.W D1 ; Check: any errors reading BM? <PWD 06Oct85>
|
|
BGE.S @1 ; If D1>0, all was well <PWD 06Oct85>
|
|
BRA.S BkAllocExit ; Otherwise give up (D0 is error code) <PWD 06Oct85>
|
|
|
|
; Allocation is done:
|
|
|
|
BkAllocOK:
|
|
BTST #7,D3 ; Did we start from the VCB's AllocPtr?
|
|
BEQ.S @2 ; If not, never mind
|
|
MOVE.W D2,D4 ; Prepare new allocPtr
|
|
|
|
; Adding in the length of the current allocation might reduce the next allocate
|
|
; call by avoiding a re-scan of the already allocated space. However, the clump
|
|
; just allocated can quite conceivably end up being truncated or released when
|
|
; the file is closed or its EOF changed. Leaving the allocation pointer at the
|
|
; start of the last allocation will avoid unnecessary fragmentation in this case.;
|
|
|
|
CMP.W VCBNmAlBlks(A2),D4 ; Is it at EOV?
|
|
BCS.S @1 ; If CS, D4 < NmAlBlks: all is well
|
|
CLR.W D4 ; If D4 >= NmAlBlks, wrap around
|
|
@1: MOVE.W D4,VCBAllocPtr(A2) ; Update VCB's allocation pointer
|
|
; <VCB is already marked dirty>
|
|
|
|
@2: ROL.L D1,D0 ; Rotate the bitmap word back into place
|
|
MOVE.L D0,0(A0,D6.W) ; And put it back where it came from
|
|
JSR MarkBlock ; Mark the buffer dirty
|
|
MOVE.L D7,D3 ; Return the actual allocation size
|
|
|
|
IF HFSDebug THEN ; <24Oct85>
|
|
MOVE.W D3,-(A6) ; Save D3 for actual return value <24OCt85>
|
|
BSR ReadBM ; Read the bitmap entry for the allocated space <24OCt85>
|
|
@5 TST.W D1 ; Found it? <24Oct85>
|
|
BMI.S @10 ; Nope - bomb. <24Oct85>
|
|
TST.L D0 ; Check - is top bit actually set? <24Oct85>
|
|
BPL.S @10 ; Nope - trouble! <24Oct85>
|
|
BSR NextBit ; OK - look for the next bit in the allocation <24Oct85>
|
|
SUBQ.W #1,D3 ; ...that's one block successfully allocated <24Oct85>
|
|
BNE.S @5 ; Go check the other blocks allocated <24Oct85>
|
|
BRA.S @20 ; Success! <24Oct85>
|
|
@10 _HFSDebug $321 ; "Pause for debugging"... <24Oct85>
|
|
@20 MOVE.W (A6)+,D3 ; Restore D3 for return to user <24Oct85>
|
|
ENDIF ; <24Oct85> MOVEQ #0,D0 ; and success
|
|
|
|
MOVEQ #0,D0 ; Sweet success
|
|
|
|
BkAllocExit:
|
|
MOVEM.L (A6)+,D1/D4-D7/A0-A1; Restore registers
|
|
MOVE.L (A6)+,-(SP) ; Restore return address
|
|
TST.W D0 ; Set condition codes for return
|
|
RTS ; And call it a day.
|
|
|
|
bkAllocFull:
|
|
MOVEQ #0,D3 ; No Blocks allocated
|
|
MOVEQ #DskFulErr,D0 ; Disk is full
|
|
BRA.S BkAllocExit ;
|
|
|
|
|
|
EJECT
|
|
;________________________________________________________________________________
|
|
;
|
|
; Routine: BlkDealloc
|
|
;
|
|
; Function: Update the bitmap to deallocate a run of disk allocation blocks
|
|
;
|
|
; Input Arguments:
|
|
; A2 - Pointer to VCB for the volume to free space on
|
|
; D2.W - First allocation block to be freed
|
|
; D3.W - Number of allocation blocks to free up (must be > 0!)
|
|
;
|
|
; Output:
|
|
; D0.W - Result code
|
|
;
|
|
; Internal register usage:
|
|
; A0 - Pointed to bitmap buffer
|
|
; D0.W - Used to hold current bitmap word
|
|
; D1.W - Count of number of bits left unexamined in D0
|
|
; D5.W - Current bitmap block number
|
|
; D6.W - Index into bitmap block buffer
|
|
;
|
|
; Side effects:
|
|
; The volume bitmap is read and updated; the volume bitmap cache may be changed.
|
|
;
|
|
; Modification history:
|
|
;
|
|
; <06Oct85> PWD Changed to check for error after calls to ReadBM and NextWord
|
|
; Now calls NextBit to read successive bits from the bitmap
|
|
;________________________________________________________________________________
|
|
;
|
|
BlkDeAlloc:
|
|
MOVE.L jBlkDeAlloc,-(SP) ; jumptable entry for vBlkDeAlloc <29Oct85>
|
|
RTS ; go there <29Oct85>
|
|
vBlkDeAlloc ; 'vectored' BlkDeAlloc routine <29Oct85>
|
|
|
|
MOVE.L (SP)+,-(A6) ; Save return address
|
|
MOVEM.L D1-D6/A0,-(A6) ; Save registers for use
|
|
MOVEQ #0,D0 ; Set up completion code
|
|
TST.W D3 ; Check block count
|
|
BEQ.S @95 ; If zero, we're done.
|
|
|
|
BSR ReadBM ; Pick up the relevant bitmap information
|
|
@10: TST.W D1 ; Any error occur? <PWD 06Oct85>
|
|
BMI.S @95 ; If not, keep going <PWD 06Oct85>
|
|
BCLR #31,D0 ; Free up the block
|
|
IF HFSDebug THEN
|
|
BNE.S @15 ; Check to make sure it was set... <PWD 24Oct85>
|
|
_hFSDebug $123 ; Pause to check this out... <PWD 24Oct85>
|
|
@15:
|
|
ENDIF
|
|
JSR MarkBlock ; Mark this buffer dirty (will be in a sec...)<PWD 06Oct85>
|
|
ADDQ.W #1,VCBFreeBks(A2) ; Adjust free block count
|
|
JSR MarkVCB ; Mark the VCB dirty
|
|
SUBQ.W #1,D3 ; That's one down: any left?
|
|
BEQ.S @90 ; No - that's it
|
|
BSR NextBit ; Get next bitmap bit <PWD 06Oct85>
|
|
BRA.S @10 ;
|
|
|
|
@90: ROL.L D1,D0 ; Rotate D0 back into position
|
|
MOVE.L D0,0(A0,D6.W) ; Put the bitmap word back where it came from
|
|
; JSR MarkBlock ; Mark the buffer dirty . . . <PWD 24Oct85>
|
|
MOVEQ #0,D0 ; success!
|
|
|
|
@95:
|
|
MOVEM.L (A6)+,D1-D6/A0 ; Restore registers
|
|
MOVE.L (A6)+,-(SP) ; Restore return address
|
|
TST.W D0 ; Set condition codes
|
|
RTS ; And call it a day.
|
|
|
|
EJECT
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: BlkChk
|
|
; Arguments: A0.L (input) -- pointer to extent record
|
|
; A2.L (input) -- VCB for volume
|
|
;
|
|
; D0.L (output) -- 0 if block was already allocated
|
|
; -1 otherwise
|
|
;
|
|
; Internal register usage:
|
|
; A0 - Pointed to bitmap buffer
|
|
; A1 - Pointed to extent record
|
|
; D0.W - Used to hold current bitmap word
|
|
; D1.W - Count of number of bits left unexamined in D0
|
|
; D2.W - Allocation block currently being checked
|
|
; D3.L - Set in case a block was found unallocated
|
|
; D4.L - Count of number of blocks in current extent
|
|
; D5.W - Current bitmap block number
|
|
; D6.W - Index into bitmap block buffer
|
|
; D7.W - Index into extent record
|
|
;
|
|
; Called By: MountVol
|
|
; Function: Make sure the extents in the extent record are marked as
|
|
; allocated in the volume bitmap. The allocation blocks mapped
|
|
; by the extent record are marked in the bitmap if they weren't
|
|
; already marked (in which case D0 is set).
|
|
;
|
|
; Modification History:
|
|
; 3-Jul-85 PWD New today.
|
|
; <06Oct85> PWD Added check for errors after calls to ReadBM and NextWord
|
|
;_______________________________________________________________________
|
|
|
|
BlkChk: MOVE.L (SP)+,-(A6) ; Save return address
|
|
MOVEM.L D1-D7/A1,-(A6) ; Save scratch registers
|
|
MOVEA.L A0,A1 ; Save away the extent record pointer
|
|
MOVEQ #0,D3 ; Clear trouble flag
|
|
MOVEQ #0,D7 ; Prepare index into extent record
|
|
|
|
@5 MOVE.W xdrStABN(A1,D7),D2 ; Pick up the first allocation block
|
|
MOVEQ #0,D4 ; Clear upper word of D4
|
|
MOVE.W xdrNumABlks(A1,D7),D4 ; Pick up length of block run
|
|
BEQ.S @90 ; If it's zero, we're all done
|
|
BSR.S ReadBM ; Pick out the bit of interest
|
|
BRA.S @50 ; Start out decrementing
|
|
|
|
@10 BSET #31,D0 ; Make sure the bit is set
|
|
BNE.S @30 ; If it was already set, allocation was OK
|
|
MOVEQ #-1,D3 ; Otherwise, raise the trouble flag.
|
|
JSR MarkBlock ; And mark the buffer dirty . .. <03Sep85>
|
|
|
|
@30 ADDQ.W #1,D2 ; Advance to the next ABN
|
|
ROL.L #1,D0 ; Rotate the bitmap long
|
|
SUBQ.W #1,D1 ; That's one fewer bits left.
|
|
BGT.S @50 ; If there are more in this D0, go for it
|
|
TST.W D4 ; Any blocks left to examine?
|
|
BEQ.S @60 ; If not, quit.
|
|
BSR NextWord ; Pick up the next bitmap longword
|
|
|
|
@50 TST.W D1 ; Any errors occur reading BM? <PWD 06Oct85>
|
|
BMI.S @95 ; If so, just punt right here & now . . . <PWD 06Oct85>
|
|
DBRA D4,@10 ; Go check next block in extent
|
|
ROL.L D1,D0 ; Rotate D0 back into position
|
|
|
|
@60 MOVE.L D0,0(A0,D6.W) ; Put the bitmap word back where it came from
|
|
ADDQ.W #lenExt,D7 ; Advance to next extent
|
|
CMP.W #lenXDR,D7 ; Hit the end of the extent record?
|
|
BLO.S @5 ; If not, continue with next extent desc.
|
|
|
|
@90 MOVE.L D3,D0 ; Return trouble flag
|
|
@95 MOVEM.L (A6)+,D1-D7/A1 ; Restore scratch registers
|
|
MOVE.L (A6)+,-(SP) ; Restore return address
|
|
TST.L D0 ; Set condition codes
|
|
RTS ; And call it a day.
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: UpdateFree
|
|
; Arguments: A2.L (input) -- VCB for volume
|
|
;
|
|
; Internal register usage:
|
|
; A0 - Pointed to bitmap buffer
|
|
; A1 - Pointed to extent record
|
|
; D0.W - Used to hold current bitmap word
|
|
; D1.W - Count of number of bits left unexamined in D0
|
|
; D2.W - Allocation block currently being checked
|
|
; D4.L - Count of free blocks
|
|
; D5.W - Current bitmap block number
|
|
; D6.W - Index into bitmap block buffer
|
|
;
|
|
; Called By: MountVol
|
|
; Function: This routine is used as part of the MountVol consistency check
|
|
; to figure out the number of free allocation blocks in the volume.
|
|
;
|
|
; Modification History:
|
|
; <08Sep85> LAK New today.
|
|
; <06Oct85> PWD Added explicit check for errors after calls to ReadBM, NextWord
|
|
; Now calls NextBit.
|
|
;_______________________________________________________________________
|
|
|
|
UpdateFree:
|
|
MOVE.L (SP)+,-(A6) ; save return address
|
|
MOVEM.L D0-D6/A0-A1,-(A6) ; save all registers used
|
|
|
|
MOVEQ #0,D4 ; start with zero free
|
|
MOVEQ #0,D2 ; start at the beginning
|
|
BSR.S ReadBM ; pick up the first bitmap block, set up D1, D0
|
|
MOVE.W VCBNmAlBlks(A2),D2 ; total number of allocation blocks
|
|
|
|
@1 TST.W D1 ; Any error reading BM? <PWD 06Oct85>
|
|
BMI.S @9 ; If so, give up now <PWD 06Oct85>
|
|
TST.L D0 ; check high bit
|
|
BMI.S @2 ; br if it's not free
|
|
ADDQ.W #1,D4 ; increment free count
|
|
|
|
@2 SUBQ.W #1,D2 ; one less block
|
|
BEQ.S @3 ; br if we've finished
|
|
BSR.S NextBit ; Pick up the next bitmap bit <PWD 06Oct85>
|
|
BRA.S @1 ; So keep trying
|
|
|
|
@3 MOVE.W D4,VCBFreeBks(A2) ; update the free block count
|
|
@9 MOVEM.L (A6)+,D0-D6/A0-A1 ; Restore registers
|
|
MOVE.L (A6)+,-(SP) ; Restore return address
|
|
RTS ; And call it a day.
|
|
|
|
EJECT
|
|
;________________________________________________________________________________
|
|
;
|
|
; Routine: ReadBM
|
|
;
|
|
; Function: Pick up the status bit for a particular block in the volume bitmap
|
|
;
|
|
; Input Arguments:
|
|
; A2 - Pointer to volume's VCB
|
|
; D2.W - Allocation block of interest
|
|
;
|
|
; Output:
|
|
; A0 - Pointed to bitmap block containing bit of interest
|
|
; D0.L - Relevant word of the bitmap, rotated so that the right bit is in [31]
|
|
; If an error is encountered reading the bitmap, D0 holds the error
|
|
; code, and D1 is negative
|
|
; D1.W - The number of bits originally to the right of the bit of interest
|
|
; D5.W - Bitmap block number (unsigned)
|
|
; D6.W - Index of relevant LongWord in bitmap block
|
|
;
|
|
; Side effects:
|
|
; The volume bitmap is read; the volume bitmap cache may be changed.
|
|
;
|
|
; Modification history:
|
|
; <06Oct85> PWD Changed to return error code and set D1 negative instead of
|
|
; calling _SysError.
|
|
;________________________________________________________________________________
|
|
|
|
ReadBM:
|
|
MOVE.L jReadBM,-(SP) ; jumptable entry for vReadBM <27Oct86>
|
|
RTS ; go there <27Oct86>
|
|
vReadBM ; 'vectored' ReadBM routine <27Oct86>
|
|
|
|
MOVE.L (SP)+,-(A6) ; Save return address
|
|
MOVE.W D2,D5 ; Copy to extract BM block number
|
|
LSR.W #8,D5 ; Shift to divide by almost 4096 (bits/block)
|
|
LSR.W #4,D5 ; Finish the division by 4096
|
|
MOVE.W D2,D6 ; Copy to compute longword index
|
|
AND.W #$0FE0,D6 ; Leave only middle 7 bits for index
|
|
LSR.W #3,D6 ; Shift to divide by 8 (bits/byte)
|
|
MOVE.W D2,D1 ; Copy to compute bit position
|
|
AND.W #$001F,D1 ; Leave only lower 5 bits (bit position)
|
|
BSR.S GetBMBlk ; Read the right bitmap block
|
|
BEQ.S @10 ; Proceed if all seems well
|
|
|
|
MOVEQ #-1,D1 ; Indicate an error occurred <PWD 06Oct85>
|
|
BRA.S @99 ; Without hope of continuing <PWD 06Oct85>
|
|
|
|
@10: MOVE.L 0(A0,D6.W),D0 ; Pick out the relevant longword
|
|
ROL.L D1,D0 ; Rotate the bit into place [MSB]
|
|
NEG.W D1 ; Subtract position from
|
|
ADD.W #32,D1 ; 32 to get number of bits left unseen
|
|
|
|
@99: MOVE.L (A6)+,-(SP) ; Restore return address
|
|
RTS ; And call it a day.
|
|
|
|
EJECT
|
|
;________________________________________________________________________________
|
|
;
|
|
; Routine: NextBit
|
|
;
|
|
; Function: Pick up the next bit from the bitmap, rolling over to the next
|
|
; bitmap block if necessary.
|
|
;
|
|
; Arguments: D0.L - Current longword under examination
|
|
; D1.W - Number of bits left unexamined in D0
|
|
;
|
|
; Side effects:
|
|
; The volume bitmap may be read, changing the cache state.
|
|
;
|
|
; Modification history:
|
|
; <06Oct85> PWD New today, filtered out of BlkAlloc/BlkDealloc
|
|
; <22Oct85> PWD Fixed bug in EOV check in FrBitScan
|
|
; <25Oct85> PWD Fixed to back up starting position before backing out at EOV.
|
|
;________________________________________________________________________________
|
|
|
|
NextBit: MOVE.L (SP)+,-(A6) ; Strip the stack for ,ASYNC I/O <PWD 22Oct85>
|
|
ROL.L #1,D0 ; Advance to next bit for examination
|
|
SUBQ.W #1,D1 ; That's one fewer left unseen
|
|
BNE.S NxtBitRTS ; If there are any left at all, we're all set.
|
|
BSR.S NextWord ; Pick up the next bitmap word
|
|
NxtBitRTS MOVE.L (A6)+,-(SP) ; Restore return address <PWD 22Oct85>
|
|
RTS ; And keep going
|
|
|
|
; Special routine for BlkAlloc free bit scan:
|
|
|
|
FrBitScan: MOVE.L (SP)+,-(A6) ; Strip the stack for ,ASYNC I/O <PWD 22Oct85>
|
|
ADDQ.W #1,D2 ; Advance the starting position <PWD 21Oct85>
|
|
BSR.S NextBit ; And go pick up the next bit <PWD 21Oct85>
|
|
@0 CMP.L MinusOne,D0 ; Quick check: is it all ones (-1)? <PWD 21Oct85>
|
|
BNE.S NxtBitRTS ; Nope: go get 'em <PWD 21Oct85>
|
|
ADD.W D1,D2 ; Advance starting block by 32 <PWD 21Oct85>
|
|
CMP.W A1,D2 ; Reached the EOV? <PWD 21Oct85>
|
|
BCC.S @10 ; Yes - look no further <PWD 22Oct85>
|
|
BSR.S NextWord ; Go straight for a new word <PWD 21Oct85>
|
|
BRA.S @0 ; And try again <PWD 21Oct85>
|
|
|
|
@10 SUB.W D1,D2 ; Restore disk position <PWD 25OCt85>
|
|
BRA.S NxtBitRts ; And go use up the remainder <PWD 25Oct85>
|
|
;________________________________________________________________________________
|
|
;
|
|
; Routine: NextWord
|
|
;
|
|
; Function: Pick up the next word from the bitmap, rolling over to the next
|
|
; bitmap block if necessary. DOES NOT MARK THE CURRENT BUFFER DIRTY.
|
|
;
|
|
; Input Arguments:
|
|
; A0 - Pointer to bitmap buffer
|
|
; A2 - Pointer to VCB for volume being worked on
|
|
; D0 - Current bitmap word
|
|
; D5 - Bitmap block number
|
|
; D6 - LongWord index of the current word in the bitmap buffer
|
|
;
|
|
; Output:
|
|
; A0 - Pointed to current bitmap block buffer
|
|
; D0 - Next bitmap word or error code [if D1 < 0]
|
|
; D1 - Number of bits left unseen in D0 (always 32), <0 on error
|
|
; D5 - Number of current bitmap block
|
|
; D6 - Advanced to index of current LongWord in the bitmap buffer
|
|
;
|
|
; Side effects:
|
|
; The volume bitmap may be read, changing the cache state.
|
|
;
|
|
; Modification history:
|
|
; <06Oct85> PWD Changed to return error instead of calling _SysError when
|
|
; bitmap cannot be read.
|
|
;________________________________________________________________________________
|
|
;
|
|
NextWord:
|
|
MOVE.L (SP)+,-(A6) ; Save return address
|
|
MOVE.L D0,0(A0,D6.W) ; Store the current word
|
|
ADDQ.W #4,D6 ; Bump the longword index
|
|
CMPI.W #512,D6 ; Have we reached the end of BM block?
|
|
BCS.S nwGetLong ; Nope - just pick out the next longword
|
|
|
|
ADDQ.W #1,D5 ; Move on to the next bitmap block
|
|
BSR.S GetBMBlk ; Read the new block in
|
|
BEQ.S nwRstIndex ; Br if we got it <03Sep85>
|
|
|
|
MOVEQ #-1,D1 ; Indicate an internal error occurred <PWD 06Oct85>
|
|
BRA.S nwExit ; Without hope of continuing <PWD 06Oct85>
|
|
|
|
nwRstIndex:
|
|
CLR.W D6 ; Reset the index to the first longword
|
|
|
|
nwGetLong:
|
|
MOVE.L 0(A0,D6.W),D0 ; Read the next word from the bitmap buffer
|
|
MOVEQ #32,D1 ; Set count for full longword
|
|
|
|
nwExit MOVE.L (A6)+,-(SP) ; Restore return address
|
|
RTS ; And call it a day.
|
|
|
|
EJECT
|
|
;________________________________________________________________________________
|
|
;
|
|
; Routine: GetBMBlk
|
|
;
|
|
; Function: Read a block out of the bitmap. The block will be read into cache
|
|
; storage; RelBMBlk should be called to write the page back to disk
|
|
; and release the storage.
|
|
;
|
|
; Input Arguments:
|
|
; D5.W - Bitmap block number
|
|
; A2 - Pointer to VCB for volume being worked on
|
|
;
|
|
; Output:
|
|
; A0 - Pointed to cache buffer containing bitmap block.
|
|
; D0 - Error code, 0 if block read successfully.
|
|
;
|
|
; Side effects:
|
|
; The volume bitmap is read; the volume bitmap cache may be changed.
|
|
;________________________________________________________________________________
|
|
|
|
GetBMBlk:
|
|
MOVE.L (SP)+,-(A6) ; Save return address
|
|
MOVEM.L D1-D2/A1-A2,-(A6) ; Save some registers from extinction
|
|
MOVE.W VCBVRefNum(A2),D0 ; Set volume refNum
|
|
MOVEQ #0,D2 ; Clear top of D2
|
|
MOVE.W VCBVBMSt(A2),D2 ; First sector in bitmap
|
|
ADD.W D5,D2 ; Compute physical block wanted
|
|
MOVEA.L VCBMAdr(A2),A1 ; Point to bitmap cache queue header
|
|
MOVEQ #kGBrelease,D1 ; release it immediately (we work on <01Oct85>
|
|
; one at a time anyway - call MarkBlock later if dirtied)
|
|
JSR GetBlock ; Actually read the sector
|
|
MOVEM.L (A6)+,D1-D2/A1-A2 ; Restore registers
|
|
MOVE.L (A6)+,-(SP) ; Restore return address
|
|
TST.W D0 ; Set status codes for return
|
|
RTS ; And call it a day.
|
|
|
|
|
|
END
|
|
|
|
|