mac-rom/OS/HFS/MFSRFN3.a
Elliot Nunn 4325cdcc78 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 09:52:23 +08:00

459 lines
16 KiB
Plaintext

;
; File: MFSRFN3.a
;
; Contains: This file contans the MFS equivalents to FXM and VSM for file block
; allocation and mapping.
;
; Copyright: © 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É
; 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.