mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 16:31:01 +00:00
4325cdcc78
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.
459 lines
16 KiB
Plaintext
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.
|
|
|
|
|