mac-rom/OS/HFS/BTALLOC.a

748 lines
25 KiB
Plaintext
Raw Normal View History

;
; File: BTALLOC.a
;
; Contains: These routines provide allocation of disk space for BTree files.
; Space is allocated in node size units, a BTree node = n logical
; blocks. Each node is identified by a node number which is the
; logical block number (relative to the file space) of the first
; block in the node.
;
; Written by: Bill Bruffey
;
; Copyright: <09> 1984-1991 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <5> 9/10/91 JSM Cleanup header.
; <4> 8/30/91 DTY Define onMac, onMacPP, and onHcMac to keep SonyEqu.a happy.
; Defined to be 0 because this file is only used for the ROM
; build, and we don<6F>t build those ROMs any more. (onMac32 is the
; base ROM.)
; <3> 9/21/90 BG Removed <2>. 040s are behaving more reliably now.
; <2> 6/20/90 CCH Added some NOPs for flaky 68040's.
; <1.3> 6/12/89 JB Fixed UpdAltMDB to handle SuperDrive; vectored UpdAltMDB.
; <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.
; <<3C>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<53>
; 9/24/86 BB Modified to use new MPW equate files.
; 1/8/86 BB Added UpdAltMDB subroutine and call to it in ExtBTFile (ROM75
; Scavenger patch). ExtBTFile now sets CacheFlag = 'TRUE' to force
; flushing following the extension of a BTree file.
; 12/19/85 BB ExtBTFile now checks for errors returned from InitNode (not
; patched in ROm75).
; 10/25/85 BB Added jump vectors for ROM versions.
; 10/17/85 BB Fixed ExtBtFile to force map record sizes to n long words.
; 10/16/85 BB Fixed AllocNode to calculate the node numbers properly when
; working with a bit map that has been extended. Fixed bug in
; ExtBTFile which was subtracting the new map node from the free
; count twice.
; 10/10/85 BB Added use of new MOVEQ equates for GetBlock and RelBlock. Added
; use of MarkBlock. Did some minor code clean up.
; 9/25/85 BB Fixed bug in ExtBTFile which was moving a long instead of a byte
; into the node type of a new map node.
; 9/23/85 BB Removed check for null node pointer in RelMap, it is now checked
; by RelNode.
; 8/29/85 BB Modified ExtBTFile to accept a partial allocation.
; 8/8/85 BB Modified ExtBTFile for new node format.
; 6/10/85 BB Cleaned up some.
; 3/15/85 BB Modified to use A6 stack.
; 3/11/85 BB Added Extend BTree File (ExtBTFile).
; 3/5/85 BB Added support for multiple map records.
; 1/17/85 BB Removed use of BTree Global area (BTG).
; 11/10/84 BB Added check for "no space".
; 10/12/84 BB Modified to use file IO instead of physical disk IO. Modified to
; use BTCB instead of VCB.
; 9/30/84 BB Modified register usage and changed to use volume refnum instead
; of drive number.
; 8/21/84 BB New today
;
;__________________________________________________________________________________
;
; External
; Routines: AllocNode - Allocates a BTree disk node.
; ExtBTFile - Extends a BTree file.
; FreeNode - Frees(de-allocates) a Btree disk node.
;
; Internal
; Subroutines: GetMap - Gets the next allocation map.
; RelMap - Releases the node containing the current
; allocation map.
;
;__________________________________________________________________________________
if (&type('onMac') = 'UNDEFINED') then
onMac: equ 0
endif
if (&type('onMacPP') = 'UNDEFINED') then
onMacPP: equ 0
endif
if (&type('onHcMac') = 'UNDEFINED') then
onHcMac: equ 0
endif
BLANKS ON
STRING ASIS
PRINT OFF
LOAD 'StandardEqu.d'
INCLUDE 'SonyEqu.a' ; for Sony format list equates
PRINT ON
PRINT NOGEN
BTAlloc PROC EXPORT
EXPORT AllocNode,ExtBTFile,FreeNode
EXPORT vAllocNode,vExtBTFile,vFreeNode,vUpdAltMDB ; <1.3>
IMPORT GetNode,RelNode
IMPORT GetRecA,InitNode
IMPORT ExtendFile
IMPORT MarkBlock
IMPORT GetBlock,RelBlock ; <08Jan86>
IMPORT FindDrive ; <08Jan86>
;__________________________________________________________________________________
;
; Routine: AllocNode
;
; Function: Allocates a BTree disk node.
;
; Input: A4.L - pointer to BTCB
;
; Output: D0.W - result code
; D1.L - node number of allocated node
;
; Called by: BTInsert,SplitLT
;__________________________________________________________________________________
AllocNode
MOVE.L jAllocNode,-(SP) ; jumptable entry for vAllocNode <25Oct85>
RTS ; go there <25Oct85>
vAllocNode ; 'vectored' AllocNode routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D2-D4/A2-A3,-(A6) ; save registers <16Oct85>
MOVEQ #0,D4 ; beg node # for current map record <16Oct85>
;
; get next map record
;
SUBA.L A2,A2 ; start with map in header node
ANGetMap
BSR GetMap ; get next map record
BEQ.S ANSearch ; ok ->
CMPI.W #BTnotfound,D0 ; map node not found?
BNE.S ANExit1 ; no, some other error ->
MOVEQ #BTnospace,D0 ; result = "no space" <14Oct85>
BRA.S ANExit1 ; exit ->
;
; search map record for a long word containing a free node (zero bit)
;
ANSearch
MOVE.W D1,D2 ; map record size <16Oct85>
LSR.W #2,D2 ; in long words <16Oct85>
SUBQ.W #1,D2 ; - 1 = loop index <16Oct85>
MOVEA.L A1,A0 ; start at beginning of the record
@1 MOVE.L (A0)+,D0 ; next map long word
CMPI.L #$FFFFFFFF,D0 ; any free blocks ?
BNE.S ANFound ; ...yes, ->
DBRA D2,@1 ; continue search <16Oct85>
EXT.L D1 ; map record size <16Oct85>
LSL.L #3,D1 ; x 8 = # of nodes <16Oct85>
ADD.L D1,D4 ; adjust beg node # <16Oct85>
BRA.S ANGetMap ; try next map record ->
;
; found a long word with some free blocks, locate 1st one
;
ANFound
MOVE.W #31,D2 ; initial bit index
@1 BTST D2,D0 ; free block?
BEQ.S @2 ; ...yes ->
DBRA D2,@1 ; try next bit
@2 BSET D2,D0 ; mark block allocated
MOVE.L D0,D3 ; save updated map long word in D3
LEA -4(A0),A0 ; position back to map long word
MOVEA.L A0,A3 ; save ptr(map long word) in A3
;
; calculate node number for the selected node
;
SUBA.L A1,A0 ; byte offset to word
MOVE.L A0,D1 ; put in D1
LSL.L #3,D1 ; x 8 = bit offset to long word
ADDI.L #31,D1 ; + bit offset within long word
EXT.L D2 ;
SUB.L D2,D1 ;
ADD.L D4,D1 ; = node number <16Oct85>
;
; check for end of map
;
MOVE.L BTCNNodes(A4),D0 ; # of nodes = max node # + 1 <16Oct85>
CMP.L D1,D0 ; target node within map range?
BGT.S ANAlloc ; yes ->
BSR RelMap ; release map node
MOVEQ #BTnospace,D0 ; result = "no space" <14Oct85>
BRA.S ANExit1 ; exit ->
;
; allocate the node
;
ANAlloc
MOVE.L D3,(A3) ; update the map
MOVEA.L A2,A0 ; mark the node dirty <10Oct85>
JSR MarkBlock ; <10Oct85>
SUBQ.L #1,BTCFree(A4) ; adjust free block count
BSET #BTCDirty,BTCFlags(A4) ; mark BTCB dirty
CLR.W D0 ; indicate no error
;
; clean up and exit
;
ANExit
BSR RelMap ; release map node
ANExit1
MOVEM.L (A6)+,D2-D4/A2-A3 ; restore regs <16Oct85>
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set up condition codes
RTS ; exit AllocNode
;__________________________________________________________________________________
;
; Routine: ExtBTFile
;
; Function: Extends a BTree file. The data fork of the BTree file is extended
; by one clump-size unit. The file may be extended by less than one
; clump if a full clump is not available. The BTree space map is
; extended to include the additional file space.
;
; Input: A4.L - pointer to BTCB
;
; Output: D0.W - result code
; 0 = ok
; BTnospace = no available disk space
; other = error
;
; Called by: BTInsert
;__________________________________________________________________________________
ExtBTFile
MOVE.L jExtBTFile,-(SP) ; jumptable entry for vExtBTFile <25Oct85>
RTS ; go there <25Oct85>
vExtBTFile ; 'vectored' ExtBTFile routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D2-D6/A2,-(A6) ; save registers
;
; extend the BTree file space (data fork)
;
MOVE.W BTCRefNum(A4),D1 ; file refnum
MOVEA.L FCBSPtr,A1 ; A1 = ptr(1st FCB)
MOVEA.L FCBVPtr(A1,D1.W),A2 ; A2 = ptr(VCB)
MOVEQ #0,D3 ; no options <08Jan86>
MOVE.L FCBClmpSize(A1,D1.W),D4 ; request one clump
JSR ExtendFile ; extend the file
BEQ.S EFCalRange ; got the space -> <02Sep85>
CMPI.W #DskFulErr,D0 ; 'disk full' error? <29Aug85>
BNE EFExit1 ; no, some other error -> <29Aug85>
TST.L D6 ; get any space? <29Aug85>
BEQ EFExit1 ; no, give up -> <02Sep85>
;
; calculate node number range for new space
;
EFCalRange
MOVE.L BTCNNodes(A4),D3 ; beg node # = current # of nodes <16Oct85>
MOVE.L D3,D4 ; D3 and D4 = beg node #
MOVE.L FCBPLen(A1,D1.W),D5 ; get new physical length
DIVU BTCNodeSize(A4),D5 ; physical length / node size
SWAP D5 ; = number of nodes
CLR.W D5 ;
SWAP D5 ;
MOVE.L D5,BTCNNodes(A4) ; update total number of nodes
SUBQ.L #1,D5 ; # of nodes - 1 = node # of ending node
MOVE.L D5,D6 ; D5 and D6 = end node #
;
; locate map positions for beginning and end of new space
;
SUBA.L A2,A2 ; start with map record in header
EFGetMap
BSR GetMap ; get next map record
BNE EFExit1 ; error ->
EXT.L D1 ; map size(bytes)
LSL.L #3,D1 ; x 8 = map size(bits)
SUB.L D1,D3 ; make relative begin/end node numbers
SUB.L D1,D5 ; ...relative to next map record
BGE.S @1 ; end node beyond this map ->
SUBQ.L #1,D4 ; adjust begin nodenum for no new map
BRA.S EFUpdFree ; update free count ->
@1 TST.L NDFLink(A2) ; have another map node?
BNE.S EFGetMap ; yes, continue search ->
;
; must extend the map, update the previous 'last' map node and release it
;
EFAddMap
MOVE.L D4,NDFlink(A2) ; link new node to last node
TST.L D3 ; new space begin within last map record?
BGE.S @1 ; no, must be all in new record ->
ADD.L D1,D3 ; make node number relative to this record
DIVU #8,D3 ; div node number
; CLR.L D0 ; by byte size <16Oct85>
MOVE.W D3,D0 ; quotient = byte offset
CLR.W D3
SWAP D3 ; remainder = bit offset
MOVEQ #7,D1 ; 7 - bit offset <16Oct85>
SUB.L D3,D1 ; = bit index
BSET D1,0(A1,D0.W) ; pre-allocate map node <16Oct85>
MOVEQ #-1,D3 ; indicate map node already allocated
@1 MOVEA.L A2,A0 ; mark the map node dirty <10Oct85>
JSR MarkBlock ; <10Oct85>
BSR RelMap ; release the map node <10Oct85>
BNE.S EFExit1 ; error -> <10Oct85>
;
; initialize a new map node
;
EFNewMap
MOVE.L D4,D1 ; map node number = begin node number
JSR InitNode ; get an initialized node
BNE.S EFExit1 ; error -> <19Dec85>
MOVE.L A0,A2 ; A2 = ptr(new map node)
MOVE.B #NDMapNode,NDType(A2) ; set node type <25Sep85>
MOVE.W #1,NDNRecs(A2) ; map is one large record
MOVE.W BTCNodeSize(A4),D1 ; D1 = node size <17Oct85>
MOVEQ #-(lenND+4),D0 ; map rec size <17Oct85>
ADD.W D1,D0 ; = nodesize - length(nd) - size(2 offsets) <17Oct85>
LSR.W #2,D0 ; round down <17Oct85>
LSL.W #2,D0 ; to long word <17Oct85>
ADDI.W #lenND,D0 ; rec offset = map rec size + length(ND) <17Oct85>
MOVE.W D0,-4(A2,D1.W) ; set free space offset <17Oct85>
; ADDQ.L #1,D4 ; don't include map node in free count <16Oct85>
TST.L D3 ; map node bit within new record?
BLT.S @1 ; no -> <10Oct85>
MOVE.B #$80,lenND(A2) ; pre-allocate 1st node (map node)
@1 MOVEA.L A2,A0 ; mark the map node dirty <10Oct85>
JSR MarkBlock ; <10Oct85>
;
; update free node count
;
EFUpdFree
SUB.L D4,D6 ; end node # - beg node # = # of nodes-1
ADD.L D6,BTCFree(A4) ; adjust free node count
BSET #BTCDirty,BTCFlags(A4) ; mark BTCB dirty
;
; clean up and exit
;
EFExit
CLR.B D0 ; result = "ok"
BSR RelMap ; release last map node
ST CacheFlag ; flush cache after extension of B-Tree files <08Jan86>
BSR UpdAltMDB ; update the alternate MDB <08Jan86>
EFExit1
MOVEM.L (A6)+,D2-D6/A2 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set up condition codes
RTS ; exit ExtBTFile
;__________________________________________________________________________________
;
; Routine: FreeNode
;
; Function: Frees (de-allocates) a Btree disk node.
;
; Input: D1.L - node number of node being released
; A4.L - pointer to BTCB
;
; Output: D0.W - result code
;
; Called by: BTDelete
;__________________________________________________________________________________
FreeNode
MOVE.L jFreeNode,-(SP) ; jumptable entry for vFreeNode <25Oct85>
RTS ; go there <25Oct85>
vFreeNode ; 'vectored' FreeNode routine <25Oct85>
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D2-D3/A2,-(A6) ; save registers
MOVE.L D1,D3 ; D3 = input node number
;
; locate map record for target node
;
SUBA.L A2,A2 ; indicate no node buffer
FNGetMap
BSR.S GetMap ; get next map record
BNE.S FNExit1 ; didn't find it ->
EXT.L D1 ; map size(bytes)
LSL.L #3,D1 ; x 8 = map size(bits)
SUB.L D1,D3 ; node within this record?
BGE.S FNGetMap ; no, get next map record ->
;
; found map record, mark node free
;
FNFound
ADD.L D1,D3 ; make node number relative to this rec
DIVU #8,D3 ; div node number
CLR.L D0 ; by byte size
MOVE.W D3,D0 ; quotient = byte offset
CLR.W D3
SWAP D3 ; remainder = bit position
MOVEQ #7,D1 ; 7 - bit position <16Oct85>
SUB.L D3,D1 ; = bit index
BCLR D1,0(A1,D0.W) ; mark node as free
MOVEA.L A2,A0 ; mark the map node dirty <10Oct85>
JSR MarkBlock ; <10Oct85>
ADDQ.L #1,BTCFree(A4) ; adjust free count
BSET #BTCDirty,BTCFlags(A4) ; mark BTCB dirty
;
; clean up and exit
;
FNExit
CLR.B D0 ; indicate no error
BSR.S RelMap ; release map node
FNExit1
MOVEM.L (A6)+,D2-D3/A2 ; restore regs
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set up condition codes
RTS ; exit AllocNode/FreeNode
;_________________________________________________________________________________
;
; Internal Subroutines
;_________________________________________________________________________________
;__________________________________________________________________________________
;
; Subroutine: GetMap
;
; Function: Gets next allocation map. If a current node buffer is not given,
; the first map record (in the BTree header node) is obtained.
;
; Input: A2.L - ptr(node buffer) containing current map record
; 0 = no current node buffer
; A4.L - pointer to BTCB
;
; Output: D0.W - result code
; 0 = ok
; BTnotfound = map record not found (end of map)
; other = error
; A2.L - ptr(cache buffer) containing next map node
; D2.L - node number of next map node
; A1.L - ptr(map record) within map node
; D1.W - size of map record (bytes)
;__________________________________________________________________________________
GetMap
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
;
; release current map node
;
MOVEQ #0,D2 ; assume map in header node <10Oct85>
MOVE.L A2,D0 ; have a current node?
BEQ.S GMGetNode ; no, get header node ->
MOVE.L NDFLink(A2),D2 ; get link to next map node
BSR.S RelMap ; release the current map node <10Oct85>
BNE.S GMExit ; error -> <10Oct85>
TST.L D2 ; have a next node?
BNE.S GMGetNode ; yes ->
MOVEQ #BTnotfound,D0 ; result = 'map record not found' <14Oct85>
BRA.S GMExit ; exit ->
;
; get next map node
;
GMGetNode
MOVEQ #0,D1 ; no GetBlock options <10Oct85>
JSR GetNode ; get map node
BNE.S GMExit ; error ->
MOVEA.L A0,A2 ; A2 = ptr(node buffer)
;
; locate map record and caculate its size
;
MOVEQ #0,D0 ; assume map record is record 0
CMPI.B #NDHdrNode,NDType(A2) ; header node?
BNE.S @1 ; no ->
MOVEQ #2,D0 ; map record is record 2
@1 MOVEA.L A2,A1 ; locate
JSR GetRecA ; ...the record
MOVE.L A0,D1 ; D1 = ptr(record)
MOVE.W NDNRecs(A2),D0 ; locate
JSR GetRecA ; ...the last record in node
MOVEA.L D1,A1 ; A1 = ptr(record)
SUBA.L A1,A0 ; map size = ptr(last record)
MOVE.W A0,D1 ; - ptr(map record)
CLR.W D0 ; result = ok
GMExit
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set up condition codes
RTS ; exit GetMap
;__________________________________________________________________________________
;
; Subroutine: RelMap
;
; Function: Releases the node containing the current allocation map. The
; node is released with no RelBlock options.
;
; Input: A2.L - pointer to current node buffer
; 0 = no node buffer
; A4.L - pointer to BTCB
;
; Output: D0.W - result code
; 0 = ok
; other = error
; A2.L - set to zero (no map node)
;__________________________________________________________________________________
RelMap
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1/A0-A1,-(A6) ; save registers
MOVEQ #0,D1 ; no RelBlock options <10Oct85>
MOVE.L A2,A0 ; ptr(node buffer) <23Sep85>
JSR RelNode ; release the node
SUBA.L A2,A2 ; indicate no map node <10Oct85>
MOVEM.L (A6)+,D1/A0-A1 ; restore registers
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set up condition codes
RTS ; exit RelMap
;__________________________________________________________________________________
;
; Subroutine: UpdAltMDB
;
; Function: Updates the extent file or catalog file info retained in the alternate
; MDB on disk. The updated info includes the PEOF and the MDB-resident
; extent record (1st 3 extents) for the BTree file being extended. The
; last-modified date (DrLsMod) is also updated.
;
; UpdAltMDB reads the Alternate MDB from disk ( via GetBlock), updates
; the extent info, and writes the block back to disk (via RelBlock).
; Note, the Alternate MDB block is left in the cache (not dirty). However,
; it is re-read from disk the next time it is to be updated.
;
; Input: A4.L - pointer to BTCB
;
; Output: D0.W - result code
; 0 = ok
; other = error
;__________________________________________________________________________________
UpdAltMDB
move.l jUpdAltMDB,-(sp) ; enter routine through RAM vector...
rts
vUpdAltMDB
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D0-D2/A0-A3/A5,-(A6) ; save registers
MOVE.W BTCRefNum(A4),D1 ; D1 = file refnum
MOVEA.L FCBSPtr,A5 ; A5 = ptr to FCB
LEA 0(A5,D1.W),A5 ;
MOVEA.L FCBVPtr(A5),A2 ; A2 = ptr to VCB
MOVE.W VCBDrvNum(A2),D2 ; drive number
JSR FindDrive ; locate drive queue element (A3 = ptr to DQE)
BNE uaExit ; no such drive, exit -> <1.3>
;
; Determine disk size. D2 is set to the disk size (in blocks). <1.3>
;
; Format List record returned by the SuperDrive version of the Sony Driver <1.3>
;
; One record per possible drive configuration is returned on a <1.3>
; Status call with csCode = 6. The entry with bit 6 in flflags set <1.3>
; is the 'current disk' configuration and is the entry used to <1.3>
; determine drive size. <1.3>
;
FmtLstRec record 0 ; <1.3>
frsize ds.l 1 ; Disk size in BYTES <1.3>
frflags ds.b 1 ; flags <1.3>
frspt ds.b 1 ; sectors per track <1.3>
frtracks ds.w 1 ; total # of tracks <1.3>
flrecsize equ * ; size of the format list record <1.3>
endr
NFRecs equ 16 ; max # of FmtLstRec to allocate on the stack <1.3>
IF (&TYPE('fmtLstCode') = 'UNDEFINED') THEN ; <1.3>
fmtLstCode equ 6 ; <1.3>
ENDIF ; <1.3>
WITH FmtLstRec ; <1.3>
movem.l a0/a2/d0/d1,-(sp) ; Save what we use... <1.3>
;
; Try the Sony Driver control call to attempt to discover <1.3>
; drive size. If it fails, revert to the old assumptions... <1.3>
;
sub.w #NFRecs*flrecsize,sp ; Make space for the format records <1.3>
move.l sp,a2 ; Save format record buffer address <1.3>
;
; Push an ioparamblk on the stack <1.3>
;
moveq #(ioQElSize+1)/2-1,d0 ; <1.3>
@1 clr.w -(sp) ; <1.3>
dbf d0,@1 ; <1.3>
move.l sp,a0 ; Parameter block address <1.3>
; Check here for Sony driver because 3rd party disk drivers don't <1.3>
; correctly support _Status calls. Some don't even check the value <1.3>
; of the CSCode parameter!!! For now, don't call any driver except <1.3>
; our own Sony driver. Maybe someday we'll get all drivers to support <1.3>
; the 'Format List' status call... <1.3>
moveq #0,d2 ; Vol size in 512-byte blocks if not a Sony <1.3>
move.w dQDrvSz(a3),d2 ; <1.3>
cmp.w #dskRfN,dQRefNum(a3) ; Is this a Sony drive? <1.3>
bne.s ckVersn ; Skip Status call if not, check DQE version..<1.3>
move.w dQDrive(a3),ioVRefNum(a0) ; drive number <1.3>
move.w dQRefNum(a3),ioRefNum(a0) ; driver refnum <1.3>
move.w #fmtLstCode,csCode(a0) ; Opcode for 'Return Format List' <1.3> <1.3>
move.w #NFRecs,csParam(a0) ; max number of format records to return <1.3>
move.l a2,csParam+2(a0) ; ptr to place to return format records <1.3>
_Status ; Ask driver for drive sizes <1.3>
bne.s guessiz ; If any error, guess the size... <1.3>
;
; Scan the returned list of format records for the entry which <1.3>
; describes the 'current disk'. <1.3>
;
move.w csParam(a0),d0 ; Number of format entries returned <1.3>
beq.s guessiz ; Go guess if driver returned zilch... <1.3>
sub.w #1,d0 ; ...for DBF loop <1.3>
@2
btst #6,frflags(a2) ; Is this entry for the 'current disk' <1.3>
bne.s @3 ; Xfer if so... <1.3>
add.w #flrecsize,a2 ; Else, point to next record <1.3>
dbf d0,@2 ; ...and try again <1.3>
bra.s guessiz ; No 'current disk' found, go guess... <1.3>
@3
move.l frsize(a2),d2 ; Get drive size in BLOCKS <1.3>
bra.s GVSzExit ; And return... <1.3>
;
; Attempt to determine the drive size by looking at the <1.3>
; drive queue element. This method used for any driver not <1.3>
; supporting the control call. <1.3>
;
guessiz
move.w #800,d2 ; assume single-sided sony <1.3>
tst.b dQDrvSz(a3) ; TwoSideFmt? <1.3>
beq.s @1 ; br if not <1.3>
add.l d2,d2 ; two-sided, double size <1.3>
@1
ckVersn
tst.w qType(a3) ; new version element? <1.3>
beq.s GVSzExit ; br if not <1.3>
move.l dQDrvSz(a3),d2 ; it's a long in the new world <1.3>
swap d2 ; but swapped for compatibility <1.3>
GVSzExit
add.w #ioQElSize+(NFRecs*flrecsize),sp ; Discard stuff on the stack <1.3>
movem.l (sp)+,a0/a2/d0/d1 ; Restore scratch registers <1.3>
ENDWITH ; <1.3>
;
; Get the alternate MDB from disk.
;
uaGetMDB
subq.l #2,d2 ; Convert disk size in blocks to alt MDB address
MOVE.W VCBVRefNum(A2),D0 ; volume refnum
MOVEQ #kGBRead,D1 ; force read option
MOVEA.L BTCCQPtr(A4),A1 ; ptr to cache queue
JSR GetBlock ; get the block (A0 = ptr to alt MDB)
BNE.S uaExit ; error, exit ->
MOVEQ #kRBTrash,D1 ; set trash RelBlock option
CMP.W #TSigWord,DrSigWord(A0) ; does it bear the Turbo signature?
BNE.S uaRelBlk ; no, release the block and exit ->
;
; Update the extent info.
;
uaUpdate
LEA DrCTFlSize(A0),A3 ; assume update for catalog
MOVEQ #FSCTCNID,D0 ; catalog BTree file?
CMP.L FCBFlNm(A5),D0 ;
BEQ.S @1 ; yes ->
MOVEQ #FSXTCNID,D0 ; extents BTree file?
CMP.L FCBFlNm(A5),D0 ;
BNE.S uaRelBlk ; no, release the block and exit ->
LEA DrXTFlSize(A0),A3 ; point to extent file info
@1 MOVE.L FCBPlen(A5),(A3)+ ; update the file size (PEOF)
MOVEQ #(lenXDR/4)-1,D0 ; length of XDR (in long words) - 1
LEA FCBExtRec(A5),A1 ; source = FCB extent record
@2 MOVE.L (A1)+,(A3)+ ; update
DBRA D0,@2 ; ...the extent record info
MOVE.L Time,DrLsMod(A0) ; update mod date also
;
; Release the block (with force write option).
;
MOVEQ #kRBWrite,D1 ; force write RelBlock option
uaRelBlk
JSR RelBlock ; release the block
uaExit
MOVEM.L (A6)+,D0-D2/A0-A3/A5 ; restore registers
uaExit1
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set up condition codes
RTS ; exit UpdAltMDB
END