mac-rom/OS/HFS/MFSRFN3.a

459 lines
16 KiB
Plaintext
Raw Normal View History

;
; File: MFSRFN3.a
;
; Contains: This file contans the MFS equivalents to FXM and VSM for file block
; allocation and mapping.
;
; Copyright: <09> 1982-1991 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <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<53>
; 10/8/85 LAK Added vector for Lg2Phys.
; 10/1/85 LAK D0 now returns a result code (no longer calls _SysError).
; 8/15/83 LAK Added safety check to prevent directory overwrites; D0 now
; returns end block + 1.
; 1/17/83 LAK Changed to add alloc blk offset in.
; 12/22/82 LAK Changed to use alloc blk size in bytes.
; 12/16/82 LAK Rewrote to reflect new file system data structures; Now passes
; back block parameter; takes allocation size into account.
;
;_______________________________________________________________________
;
; Routine: Lg2Phys
; (c) 1983 Apple Computer Inc.
;
; Arguments: A2.L (input) -- VCB ptr
; (A1,D1.W) (input) -- FCB pointer
; D4.L (input) -- number of bytes desired (multiple of 512)
; D5.L (input) -- current file position (multiple of 512)
; D3.L (output) -- physical block start for current position <01Oct85>
; D0.W (output) -- result code (0 or FSDSIntErr). <01Oct85>
; D6.L (output) -- number of consecutive bytes available, up to D4
; All other registers are preserved
; Note that Lg2Phys assumes we won't run off the end of a file.
; Called By: FileRead,FileWrite,MyRead
; Calls: GtNxBlk
; Function: Transforms file block number to volume block number and
; determines max number of consecutive disk bytes available.
;
; Modification History:
; 16 Dec 82 LAK Rewrote to reflect new file system data structures;
; Now passes back block parameter; takes allocation size
; into account.
; 22 Dec 82 LAK Changed to use alloc blk size in bytes.
; 17 Jan 83 LAK Changed to add alloc blk offset in.
; 15 Aug 83 LAK Added safety check to prevent directory overwrites;
; D0 now returns end block + 1.
; <01Oct85> LAK D0 now returns a result code (no longer calls _SysError).
; <08Oct85> LAK Added vector for Lg2Phys.
;_______________________________________________________________________
Lg2Phys
BLANKS ON
STRING ASIS
MOVE.L jLg2Phys,-(SP) ; jumptable entry for vLg2Phys <08Oct85>
RTS ; go there <08Oct85>
vLg2Phys ; 'vectored' Lg2Phys routine <08Oct85>
BSR TFSVolTst ; If it's an MFS volume, <01Oct85>
BNE.S @0 ; br for MFS file block mapping. <01Oct85>
JMP MapFBlock ; Otherwise, do the TFS file mapping <01Oct85>
@3 _HFSDebug 223 ;
@0 MOVEM.L D1-D2/D4-D5/D7,-(SP) ; preserve dem regs
MOVE.L VCBAlBlkSiz(A2),D7 ; number of bytes in an alloc blk
MOVE.W FCBSBlk(A1,D1),D3 ; start alloc block for file
IF HFSDebug THEN
MOVE.L D4,D0 ; make sure byte count is non-zero <01Oct85>
BEQ.S @3 ; 512-byte multiple . . . <01Oct85>
AND.W #$FE00,D0
CMP.W D0,D4
BNE.S @3
MOVE.L D5,D0 ; make sure byte position is <01Oct85>
AND.W #$FE00,D0 ; 512-byte multiple . . . <01Oct85>
CMP.W D0,D5
BNE.S @3
ENDIF
ADD.L D5,D4 ; current file pos + bytes desired
SUBQ.L #1,D4 ; actual ending byte.
MOVEQ #9,D1 ; shift count.
MOVEQ #0,D6 ; no bytes available so far
LSR.L D1,D4 ; end file (512-byte) block
LSR.L D1,D7 ; num of 512-byte blks in alloc blk
MOVE.L D5,D2 ; current file byte position
LSR.L D1,D2 ; current (512-byte) file block
BRA.S @2 ; br to end condition test
@1 BSR.S GtNxBlk ; get block linked to by this block
MOVE.W D5,D3 ; next linked blk -> cur block
SUB.W D7,D4 ; one alloc blk closer to the end block
SUB.W D7,D2 ; reached the desired alloc block?
@2 CMP.W D7,D2 ; less than alloc blk size?
BCC.S @1 ; keep looping until found
MOVE.W D3,D0 ; cur alloc blk
SUB.W #2,D0 ; adjust (1st alloc blk is blk 2)
MULU D7,D0 ; convert to 512-byte blocks
ADD.W D2,D0 ; add offset within alloc blk
ADD.W VCBAlBlSt(A2),D0 ; add offset to alloc blk space on disk
MOVE.L D0,-(SP) ; starting block (save for return) <01Oct85>
L2PPrt2 MOVE.W D7,D0 ; alloc blk size (mult of 512-bytes)
SUB.W D2,D0 ; number of 512-byte blks avail this
ADD.W D0,D6 ; add incremental 512-byte blks available
SUB.W D0,D4 ; done enough blocks?
BMI.S @0 ; yup.
BSR.S GtNxBlk ; no, look into the next block
MOVEQ #0,D2 ; entire alloc block
ADDQ.W #1,D3 ; check for consecutive blocks
CMP.W D3,D5 ; is it the next block?
BEQ.S L2PPrt2 ; yes, keep going
; All done- give back needed info
@0 MOVE.L (SP)+,D3 ; start physical 512-byte block <01Oct85>
MOVE.W D3,D0 ; block start
ADD.W D6,D0 ; last block in string
; this is important data, capable of trashing a diskette if wrong, so
; make sure it's in the allocation block range . . .
MOVE.W VCBAlBlSt(A2),D4 ; first 512-byte alloc block
MULU VCBNmAlBlks(A2),D7 ; number of alloc blocks
ADD.W D4,D7 ; last 512-byte alloc block + 1
CMP.W D7,D0 ; last block in range?
BHI.S @2 ; br if not
CMP.W D4,D3 ; is start block > alloc start blk?
BCS.S @2 ; br if not ok
ASL.L D1,D6 ; num blocks avail*512 = available bytes
MOVEM.L (SP)+,D1-D2/D4-D5/D7 ; restore regs
CMP.L D4,D6 ; don't allow D6 larger than D4
BLS.S @1
MOVE.L D4,D6
@1 MOVEQ #0,D0 ; success <01Oct85>
RTS
@2 MOVEM.L (SP)+,D1-D2/D4-D5/D7 ; restore regs <01Oct85>
MOVE.W #FXRangeErr,D0 ; use an appropriate TFS int err code <01Oct85>
RTS ; <01Oct85>
;_______________________________________________________________________
;
; Routine: GtNxBlk
; (c) 1983 Apple Computer Inc.
;
; Arguments: A2.L (input) -- VCB pointer
; D3.W (input) -- current block number (alloc blk size)
; D5.W (output) -- block pointed to by D3
; Preserves all registers
; Sets CCR according to D5 value
; Called By: Alloc,DAlBlks,Lg2Phys,SetEOF,SuckEmUp
; Function: Figures next block in link.
;
; Modification History:
; 16 Dec 82 LAK Reformatted
; 22 Dec 82 LAK Changed to take VCB pointer as input
; 13 Jan 82 LAK Modified for allocation blocks offset from start of disk.
;
; - note the 32K size limitation for block maps?
;_______________________________________________________________________
GtNxBlk MOVEM.L D0/A2,-(SP) ; preserve all regs used
MOVE.L VCBMAdr(A2),A2 ; get volume block map address
MOVE.W D3,D0 ; current alloc block
SUBQ.W #2,D0 ; first alloc block is number 2
MULU #BtsPrBlk,D0 ; cur blk's bit position in block map
ROR.L #4,D0 ; word bound, save bit pos in hi word
ASL.W #1,D0 ; for indexing by words
MOVE.L 0(A2,D0.W),D5 ; get the long word the block is in
CLR.W D0 ; prepare for shift count
ROL.L #4,D0 ; get shift cnt from hi word
ADD.W #12,D0 ; make into a rotate left count
ROL.L D0,D5 ; rotates proper block into low 12 bits
AND.W #$0FFF,D5 ; only give 12 bits
MOVEM.L (SP)+,D0/A2
RTS
;_______________________________________________________________________
;
; Routine: Alloc,Alloc1
; (c) 1983 Apple Computer Inc.
;
; Arguments: A2.L (input) -- VCB ptr
; (A1,D1.W) (input) -- FCB pointer
; D4.L (input) -- number of bytes extra to allocate
; D0.W (output) -- Error code, 0 if no error.
; (only error: dskfull)
; D6.L (output) -- number of bytes actually allocated (always
; a multiple of 512-bytes).
; All other registers are preserved
; Called By: FileWrite,SetEOF,FileAlloc
; Calls: GtNxBlk,SubMrk
; Function: Allocate new blocks to a file. (Does not check lock bits!)
; Alloc entry point does nothing if it can't get all the bytes
; requested; Alloc1 entry gets what it can.
;
; Modification History:
; 22 Dec 82 LAK Rewrote to reflect new file system data structures;
; No reclamation of space is now needed from undeleted
; files; always checks number of free bytes available
; on the volume before proceeding; now has 2 entry points.
; 17 Jan 83 LAK Changes for alloc blks offset from diskette start.
;
;_______________________________________________________________________
MFSAlloc
MOVE.L D4,D0 ; flag to get requested bytes or none
AllocSt MOVEM.L D1-D5/D7/A0-A3,-(SP) ; preserve all but D0, D6
MOVE.L VCBAlBlkSiz(A2),D7 ; number of bytes in an alloc blk
MOVE.L D7,D6
MULU VCBFreeBks(A2),D6 ; number of free bytes available
CMP.L D6,D4 ; pin it at number of free blocks avail
BLS.S @1
MOVE.L D6,D4 ; actual
@1 CMP.L D0,D4 ; is this enough?
BCC.S FigEndBlk ; br if so . . .
MOVEQ #DskFulErr,D0 ; report disk full
AllocXit MOVEM.L (SP)+,D1-D5/D7/A0-A3 ; restore regs used
RTS
; D4 now contains the number of extra bytes needed, and we know they are out there
FigEndBlk MOVE.L FCBPLen(A1,D1.W),D2 ; current physical length
MOVEQ #0,D6 ; bytes allocated so far
MOVE.W FCBSBlk(A1,D1),D3 ; start block for file
BNE.S @2 ; br if there is a first block
BSR.S GetFreeBk ; find a free block (put in D3)
MOVE.W D5,FCBSBlk(A1,D1.W) ; only place we set this in file system
MOVE.W D5,D3 ; now the current block
MOVEQ #1,D5 ; mark this as the ending block
BSR SubMrk
BRA.S AlCkDone ; and join in with regular alloc code
@1 MOVE.W D5,D3 ; next alloc blk in list
@2 BSR.S GtNxBlk ; get block linked to by this block
CMP.W #1,D5 ; terminal block?
BNE.S @1
; notice at this point,
; D3=current last block (alloc size)
; D2=physical file length (eventually)
; D4=bytes extra we need
; D6=# allocated already
; D7=num bytes in an alloc blk
; Now at the end of the file. start allocating
AlNxtBlk CMP.W VCBNmBlks(A2),D3 ; > # blocks on the disk?
BHI.S AlNtAtEnd ; br if so. (remember, 1st blk is #2)
ADDQ.W #1,D3 ; next blk free?
BSR.S GtNxBlk
SUBQ.W #1,D3 ; back up to block that is in file
TST.W D5 ; is it avail?
BNE.S AlNtAtEnd ; br if not
MOVE.W D3,D5 ; mark it for this file
ADDQ.W #1,D5 ;
AlLinkIn BSR SubMrk ; link block D3 to D5
MOVE D5,D3 ; now mark block D5 as 1 (EOF)
MOVEQ #1,D5
BSR.S SubMrk
AlCkDone ADD.L D7,D6 ; another block added
ADD.L D7,D2 ; extends physical length by alloc size
SUBQ.W #1,VCBFreeBks(A2) ; decrease num of free alloc blks on vol
CMP.L D6,D4 ; have we added enough?
BHI.S AlNxtBlk ; no, allocate more at the end
; have allocated all we need. restore regs, calc params, go home
MOVE.L D2,FCBPlen(A1,D1.W) ; set new physical length
BSR MarkVCB ; mark volume block map modified
MOVEQ #0,D0 ; no errors
BRA.S AllocXit
AlNtAtEnd BSR.S GetFreeBk ; find a free one with some room
BRA.S AlLinkIn ; then link it in . . .
; Comes here when we need to allocate a block but the next block in the
; file is not available (or when there are no blocks allocated to a file)
GetFreeBk MOVEM.L D0-D4/D6/A1/A3,-(SP)
SUB.L D6,D4 ; bytes needed - bytes allocated so far
CMP.L VCBClpSiz(A2),D4 ; is this more than minimum clump?
BCC.S @1 ; br if so
MOVE.L VCBClpSiz(A2),D4 ; make this our minimum search size
@1 MOVE.L VCBMAdr(A2),A1 ; block map address
MOVE.W VCBNmBlks(A2),A3 ; number of alloc blocks
ADDQ #1,A3 ; last alloc block number (1st one is 2)
MOVEQ #0,D5 ; odd/even counter
MOVEQ #2,D0 ; current block number
MOVEQ #2,D2 ; last string block number start
MOVEQ #0,D3 ; contiguous byte count
MOVEQ #0,D6 ; max contiguous byte count
CLR.W -(SP) ; block number of max string start
; we have 2 cases for the 12 bits we are after in the bit map:
;
; case 0: A1 => [nib0][nib1] [nib2][xxxx]
;
; case 1: A1 => [xxxx][nib0] [nib1][nib2]
Scan4Free MOVE.B (A1)+,D1 ; get next bitmap byte
LSL.W #8,D1 ; make room for 4-8 more bits
BCHG #0,D5 ; are we odd or even?
BNE.S @1 ; branch if we were in the middle of a byte
MOVE.B (A1),D1 ; get the next 4 bits, don't increment ptr
LSR.W #4,D1 ; move it back down to ground-zero
BRA.S @2 ; go check for free . . .
@1 MOVE.B (A1)+,D1 ; so get the other 8 . . .
AND.W #$0FFF,D1 ; we only got 4 bits so far for this case
@2 BNE.S NotFree ; br if not zero (i.e., not free)
ADD.L D7,D3 ; incr contiguous free byte count
CMP.L D6,D3 ; is this greater than our max so far?
BLS.S @3 ; br if not
MOVE.L D3,D6 ; if so, make this our new max
MOVE.W D2,(SP) ; max string block start
CMP.L D4,D3 ; is it more than we need?
BCC.S GtFreeXit ; then we are done
@3 ADDQ.W #1,D0 ; increment current block number
BRA.S NF1
NotFree ADDQ.W #1,D0 ; increment current block number
MOVE.W D0,D2 ; assume it starts a new string of freebees
MOVEQ #0,D3 ; zero current contiguous byte count
NF1 CMP.W A3,D0 ; past the end?
BLS.S Scan4Free ; br if not
GtFreeXit MOVE.W (SP)+,D5 ; get the max so far
MOVEM.L (SP)+,D0-D4/D6/A1/A3 ; restore all registers except D5 result
RTS
;_______________________________________________________________________
;
; Routine: SubMrk
; (c) 1983 Apple Computer Inc.
;
; Arguments: D3.W (input) -- block (alloc size) to mark
; D5.W (input) -- mark value to put into the 12-bits
; A2.L (input) -- VCB pointer
; All registers are preserved
; Called by: SetEOF,Alloc
; Function: Set a value into a particular location in the block map:
; puts D5 into (D3). (effectively linking D3 to D5)
;
; Modification History:
;
; 22 Dec 82 LAK Reformatted; now takes VCB ptr as input; saves all regs;
; 17 Jan 83 LAK Changed for alloc blks diskette offset.
;_______________________________________________________________________
SubMrk
MOVEM.L D0/D6/A2,-(SP) ; preserve all regs
MOVE.L VCBMAdr(A2),A2 ; need addr of disk map.
MOVE.W D3,D0 ; current alloc block
SUBQ.W #2,D0 ; first alloc block is number 2
MULU #BtsPrBlk,D0 ; cur blk's bit position in block map
ROR.L #4,D0 ; put bit shift count into high 4 bits
ASL.W #1,D0 ; make word index, don't disturb HO byte
MOVE.L 0(A2,D0.W),D6 ; get old stuff
SWAP D0 ; get shift count into low word
LSR.W #8,D0 ; get count into low order bits
LSR.W #4,D0 ; all the way down---
ADD #12,D0 ; make into a rol shift count
ROL.L D0,D6 ; get the block into the 12 ls bits
AND.W #$F000,D6 ; make it 0,
OR D5,D6 ; put new value in it.
ROR.L D0,D6 ; put it back in order
SWAP D0 ; get word index back
MOVE.L D6,0(A2,D0.W) ; stuff it back into the table
MOVEM.L (SP)+,D0/D6/A2 ; restore regs
RTS ; that's all folks
;_______________________________________________________________________
;
; Routine: DAlBlks
; (c) 1983 Apple Computer Inc.
;
; Arguments: D3.W (input) -- start of chain of blocks (of alloc size)
; A2.L (input) -- VCB pointer
; D0.W (output) -- error code
; All registers are preserved.
; Calls: GtNxBlk,SubMrk
; Called by: Delete,SetEOF
; Function:
;
; Modification History:
;
; 22 Dec 82 LAK Reformatted; preserves regs (necessary?)
; 17 Jan 83 LAK Don't preserve regs cause we don't have to.
;
; - note that deallocated blocks still exist on the diskette until allocated
; to new files and rewritten.
;_______________________________________________________________________
; DAlBlks- deallocate blocks. Enter with D3=start of chain
; exits with all blocks marked 0 in map table. does not write to disk
DAlBlks
TST.W D3 ; any blocks?
BEQ.S DAlDone ; if no blocks, all done.
@1 BSR GtNxBlk ; get the next in the chain.
MOVE.W D5,-(SP) ; save the link
CLR.W D5 ; link cur blk to 00
BSR.S SubMrk ; and mark it.
ADDQ.W #1,VCBFreeBks(A2) ; increase num of free alloc blks on vol
MOVE.W (SP)+,D3 ; next linked block
CMP.W #1,D3 ; last block?
BNE.S @1 ; no, do whole list.
BSR MarkVCB ; mark volume block map modified
DAlDone RTS ; that's all folks.