mac-rom/Toolbox/DiskInit/DiskInitHFS.a

662 lines
26 KiB
Plaintext
Raw Normal View History

;
; File: DiskInitHFS.a
;
; Contains: These routines are used to write a TFS directory onto a volume
;
; Written by: Patrick W. Dirks, December 21 1984.
;
; Copyright: <09> 1984-1992 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <6> 2/10/92 JSM Moved this file to DiskInit folder, keeping all the old
; revisions.
; <5> 8/30/91 DTY Define has3rdFloppy here since it<69>s no longer defined in
; BBSStartup.
; <4> 6/12/91 LN Removed #includes for private interfaces from public interfaces.
; Changed #include 'HardwareEqu.a' to 'HardwarePrivateEqu.a'
; <3> 5/1/90 DDG Removed the temporary conditionals that I added for Sys605.
; <2> 3/2/90 DDG Added conditionals for Sys605.
; <1.1> 11/17/89 dba got rid of checks for 64K ROMs
; <1.0> 11/16/88 CCH Added to EASE.
; 7/23/87 BB Fixed calculation of allocation block size for volumes sizes
; which are exact multiples of 32MB.
; 12/3/86 BB Adjusted maximun clump size to fix rounding error.
; 11/21/86 BB Modified to force a maximum clump size of 1MB for the catalog
; and extents files.
; 12/27/85 EHB Only use low memory default record if new ROMs
; 8/27/85 EHB Zero defaults for cache sizes (larry does it now)
; 8/26/85 EHB Added setup of NDNHeight for catalog node
; 8/12/85 DLD New version for MPW build.
; 8/9/85 PWD Added setup of record count and first and last node pointers in
; B*-Tree header
; 8/8/85 EHB Modified for variable B*-Tree node sizes
; 7/12/85 EHB Removed setup of DrNxtDirID (field all gone)
; 7/8/85 EHB Take constants from default record
; 6/27/85 EHB Crunched extensively
; 6/25/85 EHB Write spare copy of MDB at end of volume
; 6/17/85 EHB Converted for use with DiskInit package
; 5/15/85 PWD Added DrWrCnt field to MDB
; 5/10/85 PWD Added DrNmRtDirs field to MDB
; 5/6/85 PWD Changed for new FXM
; 4/22/85 PWD Added code to special-case drives 1 and 2 in volume sizing
; 4/17/85 PWD Changed to pick up volume size from Drive Queue Entry
; 3/17/85 PWD Renamed and moved 'last backup' field.
; 2/19/85 PWD Removed .Defs for MountVol and UnmountVol; TFSUtil now uses PB
; interface calls for Mount/Unmount/Eject.
; 2/11/85 PWD Changed MountVol and UnMountVol to use volume cache for all I/O
; 2/5/85 PWD Changed MountVol to split volume information over two VCB areas.
; 1/30/85 PWD Added TFSUnmount
; 1/29/85 PWD Updated to use word-long AlBlkSize fields
; 12/21/84 PWD New today.
;
; this code module is stored as a resource of type FMTR = CODE and is called by
; jumping to it's entry point. It only contains one main routine, and is only loaded
; by the format package if TFS is present in the system.
;
; <5> has3rdFloppy is false for both System and ROM builds.
;
if (&type('has3rdFloppy') = 'UNDEFINED') then ; <5>
has3rdFloppy: equ 0 ; <5>
endif ; <5>
BLANKS ON
STRING ASIS
PRINT OFF
LOAD 'StandardEqu.d'
INCLUDE 'HardwarePrivateEqu.A'
INCLUDE 'SonyEqu.A'
PRINT ON
;----------------------------------------------------------------------------------------------------
TFSFMTR PROC EXPORT
; A6 offsets. Stack frame established externally
UpDatFlg EQU -2 ; (word) used to avoid infinite update problem
OldPort EQU UpDatFlg-4 ; (long) save port
DlogResult EQU OldPort-2 ; (word) ModalDialog result
theRect EQU DlogResult-8 ; (rect) item rectangle
theItem EQU theRect-4 ; (long) item handle
theType EQU theItem-2 ; (word) item type
itemCount EQU theType-2 ; (word) number of items in list
saveRect EQU itemCount-8 ; (rect) place to save the old icon's rect <01 Jul 85>
saveIcon EQU saveRect-4 ; (long) place to save the old icon's handle <26 Jun 85>
SideCnt EQU saveIcon-2 ; (word) $0001 or $0002 depending on sides to format <21 Jun 85>
DQElPtr EQU SideCnt-4 ; (long) drive queue element ptr
DriveBlks EQU DQElPtr-4 ; (long) drive size in blocks <21 Jun 85>
StackBuf EQU DriveBlks-512 ; ( 512) large buffer for volname, disk blk
VolNameBuf EQU StackBuf-32 ; ( 32) temp buffer for volume name <21 Jun 85>
IOPBlk EQU VolNameBuf-IOVQElSize ; ( 64) parameter blk for I/O calls
; NOTE: name is read into VolNameBuf, assumes StackBuf is after to catch overflow chars
InitTFSCode
BRA.S TFSInit ; branch to code <3Dec85>
;
; Constant definitions
;
VCSize EQU 1 ; Volume cache size
VBMCSize EQU 1 ; Bitmap cache size
CtlCSize EQU 4 ; Volume control cache size
VBMSt EQU 3 ; starting block of volume bit map
KeyLen EQU 37 ; maximum key length
myFmtDefaults ; formatting constants used herein
DC.W TSigWord ; Signature word
DC.L 0 ; allocation block size (0 -> calculate it)
DC.L 0 ; clump size (0 -> calculate it)
DC.L NxFreeFN ; next free file number
DC.L 0 ; B-tree clump size (0 -> calculate it)
DC.W 0 ; reserved <EHB 27-Aug-85>
DC.W 0 ; reserved <EHB 27-Aug-85>
DC.W 0 ; reserved <EHB 27-Aug-85>
;_______________________________________________________________________
;
; Routine: TFSInit
;
; Function: This routine writes an initial TFS volume structure on
; a selected volume. It is assumed that the disk
; has already been formatted and verified.
;
; Before this routine is called, the stack buffer has been
; cleared, and the name written into it, and the TagData has
; been cleared
;
; Modification History:
;
; 01 AUG 84 BB New today.
; 12 SEP 84 BB Changed to use TFSEQU.text
; 18-Dec-84 PWD Updated volume format, integrated into TFS skeleton app.
; 6-Mar-85 PWD Changed to use extensible B*-Tree structure.
; 17-Apr-85 PWD Changed to pick up volume size from DQE.
; 6-May-85 PWD Changed for new FXM: updated MDB layout, changed initialization
; of extent tree.
; 17-Jun-85 EHB Modified for new diskInit package.
; 8-Aug-85 EHB Modified for variable B-Tree node sizes
; 26-Sep-85 EHB Made changes for >32 Mbyte volumes
;_________________________________________________________________________________
;
;
; On entry: A3 points to the stack buffer
;
; On exit: D0 contains error # (CCR set)
; A0 trashed
;
; Register conventions:
;
; A2 points to current position in MDB
; A3 points to stack buffer
; A4 points to default constants for formatting
;
; D7 Allocation block size
; D6 Clump size (XT and CT)
; D5 extent tree size in allocation blocks (XT and CT)
;_________________________________________________________________________________
TFSInit:
MOVE.L A3,A2 ; use A2 to waltz through MDB
LEA myFmtDefaults,A4 ; point to our default constants
MOVE.L FmtDefaults,D0 ; are the low-memory constants set up?
BEQ.S @1 ; => no, we're cool
MOVE.L D0,A4 ; else get new constants
@1
MOVE.W (A4)+,(A2)+ ; set volume signature
MOVE.L Time,D0 ; get the time
MOVE.L D0,(A2)+ ; set creation date
MOVE.L D0,(A2)+ ; set last backup date
CLR.L HFSTagData ; make sure HFS tag stuff is NIL <EHB 13Aug85>
MOVEQ #1,D0 ; default value for system tag and file # <EHB 13Aug85>
MOVE.L D0,TagData+10 ; set up write sequence number <EHB 13Aug85>
MOVE.L D0,TagData+2 ; set up default FilNum <EHB 13Aug85>
CLR.L (A2)+ ; DrAtrb,DrNmFls = 0
MOVE.W #VBMSt,(A2)+ ; DrVBMSt = 3
CLR.W (A2)+ ; DrAllocPtr = 0
MOVE.L DriveBlks(A6),D6 ; D6 = volume size in 512-byte blocks <20Jun85>
MOVE.L (A4)+,D7 ; D7 = allocation block size in bytes
BNE.S @2 ; => use default
; if specified allocation block size = 0, then calculate based on volume size
; ABS = 1 + (volSize/64K)
MOVE.L D6,D7 ; get volume size in 512-byte blocks
; SUBQ.L #1,D7 ; if exact block boundary, round down <23Jul87>
CLR.W D7 ; how many 64K pieces in volume?
SWAP D7 ; get into low word
ADDQ.W #1,D7 ; now round back up <11Dec85>
ASL.L #8,D7 ; Multiply by 512 for size in bytes
ADD.L D7,D7 ; D7 = allocation block size in bytes
@2 MOVE.L D6,D0 ; get volume size in 512-byte blocks
ASL.L #8,D0 ; Multiply by 256 towards size in bytes
ADD.L D0,D0 ; D0 = volume size in bytes
; After computing the number of allocation blocks to be mapped on the volume, the
; bitmap size (in 512 byte sectors) is computed from:
;
; Volume Size (Al. Blks) = 4096 * Bitmap Size (sectors) +
; Remainder to be mapped (Al. Blks)
;
; Since the Bitmap Size (the quotient) will not be mapped itself, if the remainder
; is less than or equal to the quotient after conversion to allocation blocks
; (i.e. if the number of allocation blocks occupied by the bitmap is greater than
; or equal to the number of as yet unmapped allocation blocks), everything will
; work fine. Otherwise, an additional sector will have to be allocated to
; the bitmap for the remaining allocation blocks.
DIVU D7,D0 ; divide to get volsize in alloc. blocks
AND.L #$FFFF,D0 ; ignore remainder <11Dec85>
DIVU #4096,D0 ; divide by 512*8 to get bitmap size
MOVEQ #0,D4 ; Clear high word of D4 (will contain DrAlBlSt)
MOVE.W D0,D4 ; Quotient after division (bitmap size)
SWAP D0 ; get remainder <11Dec85>
TST.W D0 ; was there one? <11Dec85>
BEQ.S @25 ; => no <11Dec85>
ADDQ.L #1,D4 ; else save one more for bitmap <11Dec85>
@25: ADDQ.W #3,D4 ; Throw in boot blocks & MDB
; D4 = DrAlBlSt
MOVE.L D6,D2 ; Pick up volume size in 512-byte blocks <20Jun85>
SUB.L D4,D2 ; Adjust for 'lost' space
LSL.L #8,D2 ; Multiply by 256
ADD.L D2,D2 ; and again by 2 to get byte count
DIVU D7,D2 ; Compute allocation block count
SUBQ #2,D2 ; Save last block for MDB copy (Like MFS)
MOVE.W D2,(A2)+ ; set DrNmAlBlks (true volume size in alloc. blocks)
; D2 = free alloc blocks in D2 (so far)
MOVE.L D7,(A2)+ ; set DrAlBlkSiz
MOVE.L (A4)+,D0 ; get clump size <EHB 26Sep85>
BNE.S @27 ; => pre-defined, use it <EHB 26Sep85>
MOVE.L D7,D0 ; else use 4*allocation block size <EHB 26Sep85>
LSL.L #2,D0 ; <EHB 26Sep85>
@27: MOVE.L D0,(A2)+ ; set DrClpSiz (file clump size) <EHB 26Sep85>
MOVE.W D4,(A2)+ ; D4 = DrAlBlSt= first mapped block on disk
MOVE.L (A4)+,(A2)+ ; set next free file number
; skip over name (already set) and a bunch of zero fields
; The XT and CT clump size is computed by dividing the original number of BLOCKS
; on the volume by 128, rounding down, and multiplying the result out to bytes again.
MOVE.L (A4)+,D0 ; examine default B-tree clump size
BEQ.S @22 ; => calculate it ourselves
MOVE.L D0,D6 ; else get B-tree clump size in bytes
BRA.S @26 ; => and go set up extent and catalog
@22 LSR.L #7,D6 ; 'Divide' by 128 to get XT & CT clump size <20Jun85>
BNE.S @23 ; If already > 0, we're all set
MOVEQ #1,D6
@23 ASL.L #8,D6 ; Multiply by 256 towards size in bytes
ADD.L D6,D6 ; D6 = XT and CT clump size in bytes
@26 MOVE.L #$100000,D0 ; max clump size is 1MB <21Nov86>
SUB.L D7,D0 ; - alloc block size (to allow for rounding) <03Dec86>
CMP.L D0,D6 ; clump size > max? <21Nov86>
BLE.S @28 ; ... no, use what we have <21Nov86>
MOVE.L D0,D6 ; ... yes, use max size <21Nov86>
@28 LEA DrVCSize(A3),A2 ; point to volume cache size
MOVE.L (A4)+,(A2)+ ; set volume cache size, volume bit map cache size
MOVE.W (A4)+,(A2)+ ; set extent and catalog B*tree cache size
LEA DrXTFlSize(A3),A2 ; Point to extent tree size
MOVE.L D6,D5 ; get clump size (XT and CT)
DIVU D7,D5 ; divide by allocation block size
SWAP D5 ; get remainder in low word
ADD.L #$FFFF,D5 ; round up high word
SWAP D5 ; D5.W = # of allocation blocks
SUB.W D5,D2 ; subtract size of extent tree
MOVE.W D5,D0 ; get # of allocation blocks
MULU D7,D0 ; get size in bytes
MOVE.L D0,(A2)+ ; save in DrXTFlSize
CLR.W (A2)+ ; start block of extent tree = 0
MOVE.W D5,(A2)+ ; length in allocation blocks
ADDQ #8,A2 ; next 2 records are 0
SUB.W D5,D2 ; subtract size of catalog tree
MOVE.W D2,DrFreeBks(A3) ; and save as number of free blocks
MOVE.L D0,(A2)+ ; DrCTFlSize in bytes
MOVE.W D5,(A2)+ ; start = end of first extent
MOVE.W D5,(A2)+ ; length = same as first extent record
LEA DrXTClpSiz(A3),A2 ; point to extent tree clump size
MOVE.L D0,(A2)+ ; Set extent tree clump size (rounded byte size)
MOVE.L D0,(A2)+ ; Set catalog tree clump size
MOVE.L D0,D6 ; and save for below
MOVEQ #2,D0 ; get initial write sequence number
MOVE.L D0,DrWrCnt(A3) ; and write it to MDB
; write master block to disk
MOVEQ #2,D1 ; block # of MDB <21Jun85>
MOVEQ #1,D2 ; 1 block long
MOVE.L D1,D3 ; tag sequence number (0 - 1st block) <21Jun85>
BSR BlkWrite ; write it to disk
BNE @95 ; Give up easily
; place a spare copy at the end of the volume
MOVE.L DriveBlks(A6),D1 ; get # of blocks on volume <25 Jun 85>
SUBQ.L #2,D1 ; disk size in blocks -2 <25 Jun 85>
MOVEQ #1,D2 ; 1 block long <25 Jun 85>
MOVE.L D1,D3 ; tag sequence number (0 - 1st block) <25 Jun 85>
BSR BlkWrite ; write it to disk <25 Jun 85>
BNE @95 ; punt on error <25 Jun 85>
; save some data from the MDB for later use
; D6 = clump size (XT and CT)
; D4 = DrAlBlSt
; #VBMSt = DrVBMSt(A3)
MOVEQ #0,D0 ; Clear top half of D0.L
MOVE.W DrNmAlBlks(A3),D0 ; Get total volume size (in alloc. blocks)
SUB.W DrFreeBks(A3),D0 ; Subtract out free blocks to get blocks taken
; set up Volume Bitmap
BSR ClrStkBuf ; clear the buffer first
MOVE.L A3,A1 ; and get pointer to the buffer
DIVU #8,D0 ; get # of $FF bytes and # of bits left
CLR.L D1 ; put # of $FF bytes
MOVE.W D0,D1 ; ... in D1
CLR.W D0 ; put # of bits left
SWAP D0 ; ... in low half of D0
TST.W D1 ; Any whole bytes to set?
BEQ @35 ; Nope - don't bother
SUBQ #1,D1 ;
@30 ST (A1)+ ; True = FF
DBRA D1,@30 ; ... in the buffer
@35 MOVE.B #$80,D2 ; assume 1 bit left
SUBQ #1,D0 ; get shift count ( # bits left - 1)
BMI @50 ; no bits to set
BEQ @40 ; 1 bit, already set
ASR.B D0,D2 ; 2-7 bits, shift them into D2
@40 MOVE.B D2,(A1) ; update the buffer
@50:
; write Bitmap to disk
MOVEQ #VBMSt,D1 ; get DrVBMSt as a long
MOVEQ #1,D2 ; 1 block long
MOVE.L D1,D3 ; tag sequence number (0 - 1st block) <21Jun85>
BSR BlkWrite ; write it
BNE @95 ; Give up without a write
BSR ClrStkBuf ; clear buffer for remaining blocks
MOVEQ #0,D2 ; <21Jun85>
MOVE.W D4,D2 ; get DrAlBlSt
SUBQ.W #VBMSt+1,D2 ; subtract drVBMSt+1 to get remaining blocks in bitmap
BEQ.S @60 ; none left
BSR BlkWrite ; write them out
BNE @95 ; keep going only while the going's good
@60:
;
; set up File extents B*-Tree
;
; set up tag data:
;
ADDQ.W #2,TagData+4 ; FilNum = 3 <EHB 13Aug85>
;
MOVEQ #0,D1 ; make block num a long <EHB 26Sep85>
MOVE.W D4,D1 ; start at first mapped block (DrAlBlSt)
MOVE.L D6,D2 ; Get extent tree clump size in bytes
MOVEQ #0,D0 ; No records in extent tree
LSR.L #8,D2 ; 'Divide' by 256
LSR.L #1,D2 ; and again by 2 to get size in blocks
MOVE.W #7,D3 ; Max. key length
BSR SetupBTree ; Set up a B*-Tree skeleton (leaves buffer clear)
BNE @95 ; Quit at the slightest hint of trouble
; Set up the file catalog B*-Tree:
; set up tag data:
ADDQ.W #1,TagData+4 ; FilNum = 4
MOVEQ #2,D0 ; There'll be 2 records in the catalog
MOVEQ #0,D1 ; make block num a long <EHB 26Sep85>
MOVE.W D4,D1 ; get first block (DrAlBlSt)
MULU D7,D5 ; Get clump size in bytes <PWD 26Sep85>
LSR.L #8,D5 ; 'divide' by 256 <PWD 26Sep85>
LSR.L #1,D5 ; and again by 2 to get size in phys. blocks<PWD 26Sep85>
ADD.L D5,D1 ; add in size in allocation blocks
MOVE.L D6,D2 ; Get catalog tree clump size (bytes)
LSR.L #8,D2 ; 'Divide' by 256
LSR.L #1,D2 ; and again by 2 to get size in blocks
MOVEQ #KeyLen,D3 ; Max. key length
BSR SetupBTree ; Set up a B*-Tree skeleton (leaves buffer clear)
BNE @95 ; Give up readily
;
; Set up the first leaf node in the tree:
; First set up the node descriptor (most of it zeros)...
ST NdType(A3) ; Node type (True = $FF) - leaf node <EHB 8Aug85>
MOVE.W #2,NdNRecs(A3) ; 2 records in node. <EHB 8Aug85>
MOVE.B #1,NDNHeight(A3) ; set node height to one for node 2 <EHB 26Sep85>
; The first record is the root directory CNode, <1>'Root':
; point to it and stuff an offset to it
LEA lenND(A3),A1 ; Point to the first key record <21Jun85>
MOVEQ #-2,D1 ; offset from end of node for offset <EHB 8Aug85>
BSR.S SetOffset ; set offset to next record <EHB 8Aug85>
; stuff the key record. First figure out the length of the key record
LEA VolNameBuf(A6),A0 ; Point to volume name <21Jun85>
MOVEQ #1,D0 ; Clear top 3 bytes + 1 for length byte <21Jun85>
ADD.B (A0),D0 ; D0 = length + 1 for blockMove <21Jun85>
MOVE.L D0,D2 ; keep rounded length in D2 <EHB 8Aug85>
ADDQ #1,D2 ; make it even <EHB 8Aug85>
BCLR #0,D2 ; by adding one and rounding <EHB 8Aug85>
MOVE.B D2,(A1) ; store key length <21Jun85>
ADDQ.B #ckrCName-1,(A1)+ ; as nameLen+bytes before name -1 <EHB 8Aug85>
CLR.B (A1)+ ; clear filler byte <EHB 8Aug85>
MOVEQ #FSRtParID,D1 ; Parent ID of root (1) <21Jun85>
MOVE.L D1,(A1)+ ; DirID in key <21Jun85>
_BlockMove ; Put the volume name as the CName <21Jun85>
ADD D2,A1 ; Advance beyond volume name <21Jun85>
; Directory CNode:
MOVE.W #$0100,(A1)+ ; Data record type (directory CNode) <21Jun85>
CLR.L (A1)+ ; Attributes/flag word & valence word <21Jun85>
MOVEQ #FSRtDirID,D1 ; Root node's directory ID is 2 <21Jun85>
MOVE.L D1,(A1)+ ; DirID <21Jun85>
MOVE.L Time,D1 ; Current date and time <21Jun85>
MOVE.L D1,(A1)+ ; Creation date time <21Jun85>
MOVE.L D1,(A1)+ ; Date and time last modified <21Jun85>
ADD.W #(lendir-dirBkDat),A1 ; bump pointer to end of record <EHB 8Aug85>
; The second record in the catalog is the root thread record: key is <2>''
; first stuff an offset to this record
MOVEQ #-4,D1 ; get offset to offset <EHB 8Aug85>
BSR.S SetOffset ; and set the offset <EHB 8Aug85>
; then stuff the record
MOVE.W #$0700,(A1)+ ; Key length = 7. <21Jun85>
MOVEQ #FSRtDirID,D1 ; get DirID <EHB 9Aug85>
MOVE.L D1,(A1)+ ; DirID in key <EHB 9Aug85>
CLR.W (A1)+ ; CName string (null) <21Jun85>
;
; Thread record:
;
MOVE.W #$0300,(A1)+ ; Record type is thread <21Jun85>
ADDQ #8,A1 ; skip over reserved bytes <EHB 8Aug85>
MOVEQ #FSRtParID,D1 ; Root's parent ID <21Jun85>
MOVE.L D1,(A1)+ ; <21Jun85>
; A0 still points to the name, D2 still contains the padded length
MOVEQ #1,D0 ; Clear top 3 bytes + 1 for length byte <21Jun85>
ADD.B (A0),D0 ; D0 = length + 1 for blockMove <21Jun85>
_BlockMove ; Copy in the volume name <21Jun85>
ADD.W #CMMaxCName+1,A1 ; make name max size <EHB 12Aug85>
; and stuff offset to empty record
MOVEQ #-6,D1 ; get the offset to the offset <EHB 8Aug85>
BSR.S SetOffset ; set the offset to the empty record <EHB 8Aug85>
; Write the node out:
MOVEQ #0,D1 ; make block num a long <EHB 26Sep85>
MOVE.W D4,D1 ; DrStAlBl + size in allocation blocks
ADD.L D5,D1 ; is starting block number
ADDQ.L #1,D1 ; Advance beyond header block
MOVEQ #1,D2 ; Write just one block <21Jun85>
MOVEQ #1,D3 ; Tag sequence number <21Jun85>
BSR.S BlkWrite ; Write the block
BNE.S @95 ; Punt on errors
;
; clean up and return:
;
MOVEQ #0,D0 ; the sweet smell of success...
@95: RTS ; and return
;------------------------
; SetOffset places an offset to a record into the node offset table
;
; Input: A1 - pointer to beginning of next record
; A3 - pointer to beginning of node
; D1 - offset to offset
;
; Output: D0,D1 - trashed
SetOffset
MOVE.L A1,D0 ; calculate offset to next record <EHB 8Aug85>
SUB.L A3,D0 ; from beginning of block <EHB 8Aug85>
ADD.W #BTNodeSize,D1 ; offset from beginning of node <EHB 8Aug85>
MOVE.W D0,0(A3,D1) ; stuff the offset <EHB 8Aug85>
RTS
;_______________________________________________________________________
;
; BlkWrite (Block Write) subroutine
;
; Input: D1 - starting block number (long)
; D2 - block count (long)
; D3 - starting tag sequence number
; A3 - Pointer to buffer to be written (StackBuf)
;
; Output: D0 - error code
; D1 - ending block number + 1
; D3 - ending tag sequence number +1
;_______________________________________________________________________
BlkWrite MOVEM.L D2/D4/A0-A2,-(SP) ; save regs
LEA IOPBlk(A6),A0 ; point to general I/O param block
LEA IODrvNum(A0),A2 ; point to first param to set up
MOVE.L DQElPtr(A6),A1 ; point to drive queue element <20Jun85>
MOVE.L DQDrive(A1),(A2)+ ; set drive number, refNum
ADDQ #6,A2 ; point to IOBuffer
MOVE.L A3,(A2)+ ; IOBuffer = stackBuf
MOVE.L #512,(A2)+ ; byte count (1 block)
CLR.L (A2)+ ; skip over IONumDone
MOVE.W #1,(A2)+ ; position mode 1 (from disk start)
BRA.S @2 ; make count (D2) 0 based
@1 MOVE.L D1,D4 ; block number <PWD 9Aug85>
LSL.L #8,D4 ; ...x 512
ADD.L D4,D4 ;
MOVE.L D4,(A2) ; ... gives disk address in bytes
MOVE.W D3,TagData+8 ; set file sequence number <EHB 13Aug85>
_Write ; write one block
BNE @3 ; exit if error
ADDQ.L #1,D1 ; increment block number
ADDQ.L #1,D3 ; ... and tag sequence number
@2 SUBQ.L #1,D2 ; do next block
BGE.S @1 ; loop until -1
@3 MOVEM.L (SP)+,D2/D4/A0-A2 ; restore regs
TST.W D0 ; Set condition codes for return
RTS
EJECT
;_______________________________________________________________________
;
; SetupBTree subroutine
;
; Input: D0 - Number of records in first node (long)
; D1 - starting block number
; D2 - block count (file size)
; D3 - Max. key length
; D4 - drive number (1=internal, 2=exernal)
; A3 - pointer to stack buffer
;
; Output: D0 - error code
;
; NOTE: This subroutine leaves the buffer completely cleared
;_______________________________________________________________________
SetupBTree:
MOVEM.L D2/D5/A2,-(SP) ; Stash regs for later use
BSR ClrStkBuf ; Empty the block buffer
MOVE.W #$8000,D5 ; mark header node as used
; Write the B*-Tree header node:
; Start with the node descriptor, which is mostly zeros...
MOVE.B #NDHdrNode,NDType(A3) ; This node contains the B*-Tree header <EHB 8Aug85>
MOVE.W #3,NDNRecs(A3) ; There are three records (header & map & user) <EHB 8Aug85>
MOVE.L D2,lenND+BTHNNodes(A3) ; set total number of nodes (before trashing D2) <EHB 8Aug85>
MOVE.L D0,lenND+BTHNRecs(A3) ; Set total number of data records <PWD 9Aug85>
BEQ @10 ; No records in B*-Tree yet, so header and bitmap are OK<PWD 9Aug85>
MOVE.W #$C000,D5 ; otherwise, mark the second node as used too
SUBQ.L #1,D2 ; Take out first block (to be written) (for below)
LEA lenND(A3),A2 ; get pointer to BTree Header
ADDQ.W #1,(A2)+ ; BTHDepth = 1 = Tree depth for empty tree (default = 0)
ADDQ.L #1,(A2)+ ; BTRoot = 1 = Root node of empty tree (default = 0)
ADDQ.L #4,A2 ; Skip BTHNRecs field <PWD 9Aug85>
ADDQ.L #1,(A2)+ ; BTHFNode = 1 <PWD 9Aug85>
ADDQ.L #1,(A2)+ ; BTHLNode = 1 <PWD 9Aug85>
@10 LEA lenND+BTHNodeSize(A3),A2 ; get pointer to buffer <EHB 9Aug85>
MOVE.W #512,(A2)+ ; BTHNodeSize = Node size
MOVE.W D3,(A2)+ ; BTHKeyLen = Max. key length
ADDQ #4,A2 ; BTHNNodes (long) already set <EHB 9Aug85>
SUBQ.L #1,D2 ; Take out 1 header node
MOVE.L D2,(A2)+ ; BTHFree = Number of free nodes
; Now for the bitmap record:
@30 LEA lenND+lenBTH+128(A3),A2 ; point to the allocation map <EHB 8Aug85>
MOVE.W D5,(A2) ; D5 contains the used bits for the allocation map <EHB 8Aug85>
; Now place offsets to the records at the end of the node
LEA BTNodeSize-8(A3),A2 ; put 4 offsets at end of node <EHB 8Aug85>
MOVE.W #lenND+lenBTH+128+256,(A2)+ ; pointer to free space <EHB 8Aug85>
MOVE.W #lenND+lenBTH+128,(A2)+ ; pointer to alloc map (256 bytes) <EHB 8Aug85>
MOVE.W #lenND+lenBTH,(A2)+ ; pointer to user space (128 bytes) <EHB 8Aug85>
MOVE.W #lenND,(A2) ; and pointer to BTH (104 bytes) <EHB 8Aug85>
MOVEQ #1,D2 ; Write just one block at a time
MOVEQ #0,D3 ; Clear tag sequence number for first block
BSR BlkWrite ; Write the header block
BNE @95 ; Surrender to the slightest opposition
; Write the remaining blocks just to set their tags:
MOVE.L (SP),D2 ; Retrieve full size (old D2)
SUBQ.W #1,D2 ; Subtract header block just written
BSR.S ClrStkBuf ; Zero it out completely
BSR BlkWrite ; Write rest of B*-Tree file
@95: MOVEM.L (SP)+,D2/D5/A2 ; Restore regs
TST.W D0 ; Set condition codes for return
RTS ; And call it a day.
ClrStkBuf MOVEM.L D0/A0,-(SP) ; save regs
LEA StackBuf(A6),A0 ; get address
MOVEQ #(512/4)-1,D0 ; get number of longs
ClrBuf CLR.L (A0)+ ;
DBRA D0,ClrBuf
MOVEM.L (SP)+,D0/A0 ; restore regs
RTS
END