mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-22 04:31:30 +00:00
2922 lines
126 KiB
Plaintext
2922 lines
126 KiB
Plaintext
;
|
|
; File: TFSVOL.a
|
|
;
|
|
; Contains: This file contains mostly volume-level routines for the Turbo
|
|
; File System.
|
|
;
|
|
; Copyright: © 1984-1993 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM8> 8/27/93 BH Backed out SetVolInfo changes from <SM7>. The flushing stuff is
|
|
; now in CmdDone.
|
|
; <SM7> 8/3/93 BH Changed MountVol to set the manual-eject flag in the VCB for
|
|
; volumes mounted in manual-eject drives. Changed SetVolInfo to
|
|
; flush changed critical volume info for manual-eject drives.
|
|
; <6> 3/10/93 gs Fix bug #1063340 in MountVol MtCheck to prevent an overflow when
|
|
; determining the maximum number of leaf records for the Catalog
|
|
; and Extents b*trees.
|
|
; <SM5> 3/9/93 CSS Fix Radar bug #1059140. The patch for UnmountForTheNineties
|
|
; was applied incorrectly. The patch only closed the control files
|
|
; on Unmounting the volume. They did this by patching only the
|
|
; _Unmount trap. SuperMario rolled it in line with FlUnMnt which is
|
|
; shared by _FlushVol and _Unmount. Rather than roll it only into
|
|
; _Unmountvol, I coditionalized the new code with a test against FlushOnly
|
|
; this should keep the code from executing in the Flush case. This is
|
|
; a lower risk solution than moving code around now (Cyclone is beta).
|
|
; <SM4> 12/1/92 RB Exported PickWDCB so it can be vectorized for FSM use.
|
|
; <SM3> 10/22/92 CSS Change some branch short instructions to branches.
|
|
; <SM2> 5/21/92 kc Append "Trap" to the names of Dequeue, EnQueue, Eject,
|
|
; UnMountVol, FlushVol, GetVol, SetVol, OpenWD, CloseWD and
|
|
; GetWDInfo to avoid name conflict with the glue.
|
|
; <SM1> 4/1/92 kc Rolled in OpenWDPatch, FixDtrmV3, MountVolFor1991, KillCheckRemountNiceWay
|
|
; NoCloseOnOffline and NoCloseOnEject and UnmountForTheNineties
|
|
; from FileMgrPatches.a
|
|
; • Pre-SuperMario comments follow •
|
|
; <2> 9/13/91 JSM Add a header.
|
|
; <1.6> 6/12/89 JB Changed UnmountVol to disallow unmounting of volumes with open
|
|
; files EXCEPT FOR the following: files with FNum < $10 (internal
|
|
; system files), files with FNum == 'GRT ' (AppleShare hack).
|
|
; External file system "internal files" are now included in the
|
|
; check such that they may unmount sucessfully with internal files
|
|
; left open.
|
|
; <1.5> 4/3/89 MSH Put in the AppleShare hack for unmount.
|
|
; <1.4> 3/21/89 CSL change JSR to DEQueue and EnQueue to BSR.L to fix link error.
|
|
; <1.3> 3/2/89 DNF removed references to forROM; HFS now builds identically for ram
|
|
; or rom
|
|
; <1.2> 11/16/88 CCH Took out include of "nTraps.a"
|
|
; <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…
|
|
; 11/4/87 JB (C958) Rolled in changes to UnmountVol from the following
|
|
; patches: PM243, PA244, PB245, and PMAB271. Moved the label
|
|
; 'FlUnMnt' 2 instructions forward (branched to only from
|
|
; UnMountVol).
|
|
; 2/19/87 BB Vectored MtCheck, FindDrive, CheckReMount, and DtrmV2.
|
|
; 12/10/86 BB Removed range check in XferVName, neither BufPtr or MemTop are
|
|
; valid upper limits in the Twitcher environment. Also added use
|
|
; of StripAddress in XferVName. [SHF: added include for ntraps.a
|
|
; for _StripAddress.]
|
|
; 10/27/86 BB Vectored DtrmV3,CkExtFS, and BMChk routines.
|
|
; 10/24/86 BB Changed range check in XferVName to use MemTop rather than
|
|
; BufPtr.
|
|
; 10/2/86 BB Fixed bug in MountVol (wasn't saving D0 accross a CmpString
|
|
; call.
|
|
; <C193> 10/1/86 WRL Set offset to zero before doing VCB pointer check in routine
|
|
; CkWDRefnum in TFSVOL.a.
|
|
; 9/16/86 BB Fixed rename problem in MountVol (use of pointer to a cache
|
|
; buffer).
|
|
; 9/15/86 BB Added check for a zero VCB pointer in CkWDRefNum indicating that
|
|
; the WD is already closed.
|
|
; 4/15/86 PWD fix bug in GetWDRefNum (one path forgot to init high word of D1
|
|
; before doing a DIVU.
|
|
; 1/13/86 LAK Incorporated fix to remount check from ROM75Fix.
|
|
; 10/29/85 LAK Vectored DtrmV1 routine.
|
|
; 10/28/85 PWD Changed to pass control call to drivers anyway if 64 <= DIP <=
|
|
; 127 mung VCB as for _Offline call for these drivers. Changed
|
|
; NoEject from byte-boolean to a tri-state flag: -1 [offline], 0
|
|
; [eject], or +1[special eject call].
|
|
; 10/27/85 PWD Changed _GetVolInfo to ignore volume control files in
|
|
; determining volume busy status. Set attributes bit 5 if default
|
|
; on this volume.
|
|
; 10/24/85 LAK Fixed Eject bug (FlushBuffers wasn't preserving D2 which FClose
|
|
; clobbers).
|
|
; 10/20/85 LAK Added LEOF remount checking for MFS volumes.
|
|
; 10/14/85 PWD Added ReadWDCB routine for external file system support. Moved
|
|
; remount check to last step in MountVol. Added DumpCaches routine
|
|
; to dispose of cache blocks with defunct VRefNum/VCBPtr [on
|
|
; remount]. Added LEOF check again.
|
|
; 10/13/85 PWD Fixed bug in GetVolInfo: don't try to read working directory
|
|
; valence for external FS volumes.
|
|
; 10/11/85 PWD Changed GetVolInfo to pin NmAlBlks and NmFrBlks at
|
|
; (32767*1000)/1024 instead of 32767 for programs that figure in
|
|
; 'decimal K'
|
|
; 10/11/85 PWD Backed out of LEOF check on remount for Beta-ROMs. The current
|
|
; algorithm fails to correctly back out of a remount attempt,
|
|
; leaving the original VCB changed. Maybe we can dispose of it
|
|
; somehow?? Restore its original state??
|
|
; 10/10/85 LAK Call new routine MarkVCBDirty for Eject/Unmount and Mount to
|
|
; avoid changing the modification date for just the consistency
|
|
; bit (Finder gets infinitely confused otherwise in resync loop on
|
|
; single-drive system).
|
|
; 10/7/85 PWD Changed to separate out BMChk routine, use it to check 1st
|
|
; B*-Tree extent allocation status. Added code to check LEOF of
|
|
; open file on remount.
|
|
; 10/6/85 PWD Threw in SetVolName for use in SetVolInfo (from TFSDir2).
|
|
; 10/4/85 PWD Fixed bug in GetVol, SetVol (test D1 bit rather than IOTrap(A0)
|
|
; bit).
|
|
; 10/1/85 LAK Munged MountVol a lot to share code with MFS mount (which now
|
|
; uses the volume cache). Removed AdjustIntErr: this function is
|
|
; now done in CmdDone. MountVol modified to test for
|
|
; Offline/Ejected vol after call to GetVCBDrv which now also looks
|
|
; for these. No longer save first 4 bytes of non-Mac disk in
|
|
; FSTemp4 for Format package since it can't tell anyways. Call
|
|
; Offline on TMFOErr also at MountVol.
|
|
; 9/30/85 PWD Move PMSP hook to correct place. If HFSBit is set in GetVol
|
|
; call, go to GetDir.
|
|
; 9/26/85 PWD Added SetupDef entry point for raw internal access from external
|
|
; FS.
|
|
; 9/25/85 PWD Overhauled PMSP: removed root from directories considered; added
|
|
; support for PMSPHook and PMSP Enable/Disable calls. Left
|
|
; interrupts enabled during search of FCB table.
|
|
; 9/24/85 PWD Fixed bug (MOVE.L vs. MOVEM.L) in directory valence lookup in
|
|
; GetVolInfo
|
|
; 9/24/85 PWD Changed SetVol to branch to SetDir when TFS bit is set.
|
|
; 9/22/85 PWD Fixed setting of DefVRefNum in SetVol, changed OpenWD to allow
|
|
; MFS volumes as argument if directory is root, changed HSetVol
|
|
; (a.k.a. SetDir) to allow MFS volumes specified by name, changed
|
|
; MountVol to set up new VCB fields for B*-Tree allocation sizes,
|
|
; changed GetVolInfo to subtract B*-Tree allocation from NmAlBlks,
|
|
; and return directory valence instead of root valence if
|
|
; directory referenced is not the root.
|
|
; 9/21/85 LAK Call FlushCache with D0=volume refnum, not 0 (this option no
|
|
; longer supported). This is more efficient (we used to trash all
|
|
; cache blocks for all volumes when we ejected or unmounted a
|
|
; volume) as well as being easier on the cache.
|
|
; 9/8/85 LAK Don't mount the volume if a catalog loop is detected. Call
|
|
; UpdateFree as part of MountVol consistency check. Zero roving
|
|
; allocation ptr on mount. Save first 4 bytes of non-Mac disk in
|
|
; FSTemp4 for Format package so it can discern Apple II diskettes.
|
|
; 9/6/85 LAK Slight modification to DtrmV3 prefix to prevent passing to
|
|
; DtrmVol if IOFileName points to a zero-length string (for the
|
|
; dubious result of making CatMove work with a zero-length string
|
|
; . . .).
|
|
; 9/5/85 LAK Set CacheFlag before flushing control cache.
|
|
; 8/31/85 LAK Made XferVName a bit more robust. Fixed GetWDInfo call bug.
|
|
; Mount scan now sets an inconsistent bit if it had to mark a bit
|
|
; in the allocation map . . .
|
|
; 8/30/85 LAK Added calls to TrashVBlks for Mount/UnmountVol. Rewrote
|
|
; DtrmVl/3. Fixed bug causing extents tree scan to be skipped.
|
|
; 8/29/85 LAK Call FlushMDB BEFORE closing the catalog and extents file FCBs
|
|
; in UnMountVol. Rewrote Eject mess . . . it's always synchronous
|
|
; now.
|
|
; 8/28/85 LAK Some changes to use WDCB lookup routines in TFSDir2.
|
|
; 8/27/85 LAK Much munging and saving in the InitCache, RelCache stuff.
|
|
; 8/22/85 PWD Changed _HGetVolInfo to return VRefNum in ioVRefNum field.
|
|
; 8/15/85 PWD Changed _GetVolInfo to return ioVFilCnt and ioVDirCnt.
|
|
; 8/6/85 PWD Fixed bugs in external FS treatment: changed _(TF)GetVolInfo to
|
|
; pass control to external FS AFTER stuffing I/O PB fields.
|
|
; 7/12/85 PWD Added MarkVCB routine to set VCB dirty instantly
|
|
; 7/11/85 PWD Moved FlushMDB routine into TFSCommon
|
|
; 6/29/85 PWD Fixed bug in mount to set up default WDCB when first volume is
|
|
; mounted in addition to setting DefVCBPtr.
|
|
; 6/20/85 PWD Changed to use combined file/directory CNode numbering Changed
|
|
; to return volRefNum on GetVolInfo and GetWDInfo ONLY if no WDCB
|
|
; was specified, or if a volume name was used.
|
|
; 6/19/85 PWD Changed non-hardware internal errors to FSDSIntErr instead of
|
|
; IOErr.
|
|
; 5/14/85 PWD Added SetVolInfo trap.
|
|
; 5/11/85 PWD Changed MountVol to share caches between volumes in a system to
|
|
; allow use on 128K machines
|
|
; 5/10/85 PWD Added TFGetVolInfo
|
|
; 5/1/85 PWD Added GetWDInfo
|
|
; 4/25/85 PWD Changed _Eject to leave non-ejectable volumes online, but call
|
|
; the driver anyway. Fixed code to turn all disk errors into IOErr
|
|
; before returning to the user.
|
|
; 4/25/85 PWD Fixed bug in OpenWD due to missing BRA to successful completion
|
|
; Fixed bug in GetWDCBRfn from double offset.
|
|
; 4/22/85 PWD Fixed FlushVol to write VCBLsMod date.
|
|
; 3/14/85 PWD Added WD code (OpenWD, CloseWD, SetDir, GetDir).
|
|
; 3/12/85 LAK FSVol/Eject: save and restore IOCompletion address over async
|
|
; FlushVol call (so Eject part of Eject may be done
|
|
; asynchronously).
|
|
; 2/12/85 PWD Adapted for use in Turbo FS from original Mac FS code: split
|
|
; MFS-specific code off into MFSVol, changed MountVol, UnMountVol,
|
|
; FlushVol, OffLine and Eject to handle TFS volumes and pass MFS
|
|
; volume matters to appropriate MFSVol entries. Added
|
|
; FindFCB,AccessBT, and FreeFCB routines
|
|
; 1/25/85 LAK Uncommented status call in MountVol. Use EnQueue, DeQueue
|
|
; routines directly.
|
|
; 8/7/84 GSS New today.
|
|
;
|
|
;
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; External Routines: MountVol,UnMountVol,GetVol,SetVol,
|
|
; FlushVol,GetVolInfo,SetVolInfo,Eject,Offline,
|
|
; OpenWD,CloseWD,SetDir,GetDir
|
|
;
|
|
; Internal Routines: DtrmVol,FindDrive,CVFlgs,CkExtFS,
|
|
; FindFCB,AccessBT
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
|
|
;_______________________________________;
|
|
; ;
|
|
; MakeStkPB utility . . . ;
|
|
;_______________________________________;
|
|
|
|
|
|
BLANKS ON
|
|
STRING ASIS
|
|
|
|
MakeStkPB MOVE.L (SP)+,A0
|
|
MOVEQ #(IOVQElSize/2)-1,D0
|
|
@1 CLR.W -(SP) ; get IO param block off stack
|
|
DBRA D0,@1 ; (with IOFileName zeroed)
|
|
MOVE.L A0,-(SP)
|
|
MOVE.L SP,A0
|
|
ADDQ #4,A0
|
|
RTS
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: MountVol
|
|
; Arguments: A0 (input) -- pointer to volume parameter block, uses:
|
|
; IOVDrvNum (name not allowed)
|
|
; D0 (output) -- error code
|
|
; This call is executed synchronously.
|
|
; Calls: FSQueueSync,GetVCBDrv,GetVCBRfn,FindDrive,CmdDone,
|
|
;
|
|
; Function: The VCB pointers are checked to see if a volume in the
|
|
; specified drive is already on-line (error if so). Reads in the
|
|
; directory master block and allocates memory for VCB and additional
|
|
; data structures, depending on the volume type:
|
|
;
|
|
; - For MFS volumes (handled in MFSVol), space is allocated for
|
|
; a volume buffer, as well as the block map, which is read in
|
|
; from disk).
|
|
;
|
|
; - For TFS volumes, space is allocated for a bitmap cache, a volume
|
|
; control cache (for B*-Tree use), and a volume cache. In addition,
|
|
; two FCBs are used by the B*-Trees.
|
|
;
|
|
; No new VCB storage is allocated for remounts.
|
|
;
|
|
; Fix _MountVol to
|
|
; not allocate any memory during disk switch operations.
|
|
; not attempt to _Offline other volumes to free up memory
|
|
; not reopen btree files on remounts
|
|
;
|
|
; In order to make the disk switch hook run without moving memory, we need
|
|
; to be able to check for a remount without moving memory. If we find a
|
|
; remount, we succeed. If we see the #fsNoAllocate flag, we'll return an
|
|
; error, causing the disk switch code to eject the disk and wait for another.
|
|
; Otherwise we jump into the ROM and let it do a new mount.
|
|
;
|
|
; When we do see a remount, we tweak the driver refNum and drive number and
|
|
; we're done, since the btree files will always be open.
|
|
;
|
|
; The flag #fsNoAllocate will be set by the disk switch hook to inform the
|
|
; file system that it should allow only remounts (i.e. not allocate any memory).
|
|
; If new mounts are allowed, we jump straight into the ROM code which mounts the
|
|
; volume, skipping the old code which attempted to _Offline other mounted
|
|
; volumes in favor of a newly mounted one.
|
|
;
|
|
; Exciting note for you wanna-be assemblers out there who write instructions
|
|
; into lomem at TrapAgain and jump to them. You know who you are (Disk Switch
|
|
; Hook). You might have been worried about flushing those whizzy processor
|
|
; caches that some of our more profitable macintoshes sport these days. However,
|
|
; as an added introductory bonus, successful mountvol calls flush the caches
|
|
; because they call _BlockMove when they fill in the fresh VCB from the MDB.
|
|
; _BlockMove is just one of those cache-flushing kind of guys.
|
|
;
|
|
; Modification History:
|
|
;
|
|
; 07 Aug 84 GSS New today
|
|
; 26 Oct 84 RFA Commented out Status call since Ron's driver doesn't support it
|
|
; 25 Jan 85 LAK Uncommented above call for Mac.
|
|
; 12 Feb 85 PWD Adapted for use with TFS Volumes; pass control to MFSMount
|
|
; for MFS volumes.
|
|
; 14 Feb 85 PWD Changed to link VCB into VCB queue immediately (it's needed
|
|
; for GetBlock to work. Unlink before passing control to MFSVol
|
|
; 27-Feb-85 PWD Fixed cache release code: use RelCache to dispose of vol. cache,
|
|
; and removed vol. cache code from DsposCaches (vol. cache is
|
|
; released in DsposBuf).
|
|
; 25-Apr-85 PWD Changed to return IOErr on internal errors.
|
|
; 11-MAy-85 PWD Changed to allocate caches only for first TFS volume, and share
|
|
; the caches on a system-wide basis with subsequently mounted volumes.
|
|
; 24-Jun-85 PWD Changed to update root name from volume name in VCB on mount
|
|
; 23-Jul-85 PWD Changed disk recognition algorithm to use only SigWord,
|
|
; CrDate, and volume name.
|
|
; 24-Jul-85 PWD Added increment of VCBWrCnt on mount to account for last
|
|
; write of MDB. Changed to copy information fresh from MDB
|
|
; into existing VCB on remount.
|
|
; 22-Aug-85 PWD Changed to flush MDB after mount with consistency flag cleared.
|
|
; <27Aug85> LAK Got rid of all calls to InitCache, RelCache. Added subroutine
|
|
; AdjustIntErr. Removed support for SysCRefcnt. Minor cleanup.
|
|
; <30Aug85> LAK Fixed bug causing extents tree scan to be skipped.
|
|
; <08Sep85> LAK Don't mount the volume if a catalog loop is detected. Call UpdateFree
|
|
; as part of MountVol consistency check. Zero roving allocation ptr on
|
|
; mount.
|
|
; 22-Sep-85 PWD Added code at mount to compute VCBXTAlBks and VCBCTAlBks.
|
|
; <01Oct85> LAK Removed AdjustIntErr: this function is now done in CmdDone.
|
|
; <07Oct85> PWD Changed to check 1st B*-Tree extent allocations status in cons. check
|
|
; Changed to check LEOF of open files on remount.
|
|
; <11Oct85> PWD Backed out of LEOF check on remount for Beta-ROMs.
|
|
; <14Oct85> PWD Changed to do all remount checking (including LEOF) immediately before
|
|
; a successful return.
|
|
; <03Nov85> LAK Fixed bug in MountVol out-of-memory (Mountvol has replaced IODrvNum in
|
|
; user parameter block with bogus vrefnum).
|
|
; This helps us in tight memory situations.
|
|
;_______________________________________________________________________
|
|
; Rolled in MountVolFor1991 patch from FileMgrPatches.a <SM1>
|
|
MountVol:
|
|
bsr FSQueueSync ; wait until all current calls are done
|
|
|
|
movea.l a0, a5 ; save caller's pb
|
|
move.w ioDrvNum(a5), d2 ; where FindDrive likes it
|
|
bsr FindDrive ; get driver refnum in D1 (drive num still in D2)
|
|
bne MtVolDone
|
|
|
|
suba.w #512,a6 ; a disk block
|
|
|
|
lea.l Params,a0 ; the old lomem param block
|
|
move.w d2,ioDrvNum(a0) ; drive number
|
|
move.w d1,ioRefNum(a0) ; driver RefNum
|
|
move.l a6,ioBuffer(a0) ; buffer
|
|
move.w #fsFromStart,ioPosMode(a0) ; position mode 1 (from disk start)
|
|
move.l #1024, ioPosOffset(a0) ; The MDB is always block #2
|
|
move.l #512,ioByteCount(a0) ; All MDBs are 1 512 byte block
|
|
_Read
|
|
bne RemountExit
|
|
|
|
moveq.l #NoMacDskErr,d0 ; Assume it's for another file system.
|
|
cmp.w #tSigWord,drSigWord(a6) ; Does it bear the Turbo Seal?
|
|
beq.s @GotMacDisk
|
|
|
|
cmp.w #sigWord,drSigWord(a6) ; Is it a trustworthy MFS volume?
|
|
bne RemountExit
|
|
@GotMacDisk:
|
|
|
|
moveq.l #badMDBErr,d0 ; in case master directory block is bad
|
|
move.l drAlBlkSiz(a6),d3 ; make sure this is non-zero, 512 multiple
|
|
beq RemountExit ; exit if 0
|
|
andi.w #$01FF,d3 ; 512-byte multiple?
|
|
bne RemountExit ; exit if not
|
|
|
|
move.w #notARemountErr,d0 ; 'cause we're looking for remounts only here
|
|
move.l VCBQHdr+qHead,d3 ; search the queue of VCBs
|
|
|
|
CheckRemountLoop:
|
|
beq RemountExit ; we fail if we don't see a remount <SM3> CSS
|
|
move.l d3,a2
|
|
|
|
tst.w vcbDrvNum(a2) ; matching volume better be off-line (0 drive num)
|
|
bne.s @Next
|
|
|
|
move.w vcbSigWord(a2),d3 ; Pick up Sigword of mounted volume
|
|
cmp.w drSigWord(a6),d3 ; Same signature?
|
|
bne.s @Next
|
|
move.l vcbCrDate(a2),d3 ; Pick up creation date of mounted volume
|
|
cmp.l drCrDate(a6),d3 ; Same create date?
|
|
bne.s @Next
|
|
move.l vcbLsMod(a2),d3 ; Pick up mod date of mounted volume
|
|
cmp.l drLsMod(a6),d3 ; Same mod date?
|
|
bne.s @Next
|
|
|
|
; At this point, we're fairly certain that the two volumes are, in fact, the same,
|
|
; but just to make sure (and avoid problems with stuck clocks), we'll compare the
|
|
; volume names as well:
|
|
|
|
lea.l vcbVN(a2),a1 ; Point to name of mounted volume
|
|
lea.l drVN(a6),a3 ; Point to name of current volume
|
|
moveq.l #(vcbMaxNam+1)-1,d3 ; check 28 bytes in name field (incl. length)
|
|
@loop:
|
|
cmpm.b (a1)+,(a3)+ ; field match?
|
|
dbne d3,@loop
|
|
beq.s Remount
|
|
|
|
@Next:
|
|
move.l qLink(a2),d3
|
|
bra.s CheckRemountLoop
|
|
|
|
; We are now convinced that we have a remount. We will rebuild the attributes
|
|
; byte, which is the only one that could have changed. We'll also store the
|
|
; current drive number and driver refNum, and mark the volume dirty.
|
|
Remount:
|
|
move.w #drvStsCode,csCode(a0) ; drive status!
|
|
clr.b 2+csParam(a0) ; Clear status byte for return
|
|
_Status ; refnum and drivenum set up by read call
|
|
|
|
moveq.l #-128,d0 ; $80 mask
|
|
and.b 2+csParam(a0),d0 ; WriteProt status get
|
|
move.b d0,vcbAtrb+1(a2) ; write-protect, zeroed consistency status
|
|
_AssumeEq vcbWrProt,7
|
|
|
|
move.w d2,vcbDrvNum(a2) ; drive number
|
|
move.w d1,vcbDRefNum(a2) ; driver RefNum
|
|
IF hasManEject THEN ; <SM7> <BH 03Aug93>
|
|
BSR SetVCBManEject ; set vcb maneject flag appropriately <SM7> <BH 03Aug93>
|
|
ENDIF ; <SM7> <BH 03Aug93>
|
|
|
|
jsr TFSVCBTst ; remounted a TFS volume? <32>
|
|
bne.s NoRemountErrExit ; Nope - don't mess with the MDB <33>
|
|
btst.b #vcbWrProt,vcbAtrb+1(a2); Is volume write protected? <32>
|
|
bne.s NoRemountErrExit ; If so, don't try to flush the MDB <33>
|
|
bclr.b #vcbAtVOK,vcbAtrb(a2) ; From now 'til unmount we're dirty <32>
|
|
jsr MarkVCBDirty ; mark VCB dirty so it will be written <32>
|
|
jsr FlushMDB ; write it <32>
|
|
|
|
NoRemountErrExit:
|
|
moveq.l #noErr,d0
|
|
|
|
RemountExit:
|
|
adda.w #512, a6 ; deallocate MDB buffer
|
|
|
|
tst.w d0 ; check the error
|
|
beq.s CmdDone ; noErr implies a successful remount
|
|
|
|
; if we are allowing new mounts, let the ROM handle the details. Otherwise,
|
|
; let the error stand
|
|
move.l FSVarsPtr,a1
|
|
btst.b #fsNoAllocate, FSVars.fsFlags(a1)
|
|
bne CmdDone ; let the error stand
|
|
|
|
ST NewMount ; assume now that it's a new volume
|
|
|
|
; First see if the disk is already mounted.
|
|
|
|
mv_Start MOVEQ #ParamErr,D0
|
|
MOVE.W IOVDrvNum(A0),D2 ; drive number
|
|
BLE.S toMVDone ; br if none specified
|
|
|
|
MOVE.W D2,D0 ; see if there's a vol already mounted
|
|
BSR GetVCBDrv ;
|
|
BNE.S mv_getDrive ; br if not
|
|
TST.W VCBDrvNum(A2) ; is it offline? <01Oct85>
|
|
BEQ.S mv_getDrive ; br if so . . . (probably a remount) <01Oct85>
|
|
MOVEQ #VolOnLinErr,D0 ; report an error
|
|
toMVDone BRA MtVolDone
|
|
|
|
; Find the appropriate drive queue entry and allocate a VCB.
|
|
|
|
mv_getDrive:
|
|
BSR FindDrive ; get driver refnum in D1 (drive num still in D2)
|
|
BNE.S toMVDone ; br if not found or for external FS
|
|
|
|
MOVE.L A0,A2 ; preserve A0 a bit
|
|
MOVE.L #VCBLength,D0 ; get memory for VCB
|
|
_NewPtr ,SYS,CLEAR ; off the system heap, zeroed
|
|
|
|
; Note: VCBFSID,VCBDirIndex,VCBFlags are 0, as well as VCBXTRef, VCBCTRef,
|
|
; VCBMAdr, VCBCtlBuf, and VCBBufAdr.
|
|
|
|
BNE.S toMVDone ; exit if we got no memory
|
|
LEA VCBQHdr,A1 ; Point to head of VCB queue
|
|
TST.L QHead(A1) ; Check: is queue empty right now?
|
|
BNE.S @1 ; If not, never mind
|
|
|
|
MOVE.L A0,DefVCBPtr ; If empty, this is now default, too.
|
|
MOVE.L WDCBsPtr,A1 ; Point to WDCB array
|
|
MOVE.L A0,WDVCBPtr+2(A1) ; Set default VCB pointer in default WDCB
|
|
MOVEQ #FSRtDirID,D0 ; Default to root directory
|
|
MOVE.L D0,WDDirID+2(A1) ; Set directory to default to
|
|
CLR.L WDCatHint+2(A1) ; Clear catalog hint
|
|
CLR.L WDProcID+2(A1) ; And procID of WDCB 'owner'
|
|
LEA VCBQHdr,A1 ; Reset A1 for VCB insertion
|
|
|
|
@1 JSR EnqueueTrap ; Insert the new VCB in the queue
|
|
EXG A0,A2 ; VCB ptr
|
|
MOVE.W D2,VCBDrvNum(A2) ; put drive number
|
|
MOVE.W D1,VCBDRefNum(A2) ; and driver refnum into VCB
|
|
IF hasManEject THEN ; <SM7> <BH 03Aug93>
|
|
BSR SetVCBManEject ; set vcb maneject flag appropriately <SM7> <BH 03Aug93>
|
|
ENDIF ; <SM7> <BH 03Aug93>
|
|
|
|
MOVEA.L SysVolCPtr,A1 ; set up A1
|
|
MOVE.L A1,VCBBufAdr(A2) ; always use system-wide cache . . .
|
|
|
|
; Assign a refNum to this new volume.
|
|
|
|
MOVEQ #0,D0 ; Begin with a clean slate
|
|
mv_GetVRef SUBQ.W #1,D0 ; Start with -1 and count down
|
|
MOVEM.L D0/A2,-(SP)
|
|
BSR GetVCBRfn ; Check if already assigned
|
|
MOVEM.L (SP)+,D0/A2 ;
|
|
BEQ.S mv_GetVRef ; If EQ, VRefNum already assigned
|
|
|
|
MOVE.W D0,VCBVRefNum(A2) ; note for us
|
|
CMP.L DefVCBPtr,A2 ; Are we supposedly the default?
|
|
BNE.S mv_GetMDB ; Nope - don't worry about it.
|
|
MOVE.W D0,DefVRefNum ; Set up default VRefNum now, too
|
|
|
|
; Now try reading in the master directory block.
|
|
|
|
mv_GetMDB:
|
|
MOVEQ #0,D1 ; Clear flag bytes
|
|
MOVEQ #2,D2 ; MDB is always block 2 (third block on disk)
|
|
JSR GetBlock ; With A1 still pointing to volume CQH.
|
|
BNE MtVolEr2 ; Quit & Release VCB on errors <02Sep85>
|
|
MOVE.L A0,A5 ; Save buffer ptr for later <01Oct85>
|
|
|
|
; Now check what manner of animal we have before us:
|
|
|
|
MOVEQ #kRBTrash,D1 ; trash it in case VCB gets reused . . .<01Oct85>
|
|
JSR RelBlock ; Release hold on cache block <02Sep85>
|
|
|
|
CMP.W #TSigWord,DrSigWord(A5) ; Does it bear the Turbo Seal? <08Sep85>
|
|
BEQ.S mv_GotMDB ; If so, give it the full treatment <01Oct85>
|
|
|
|
MOVEQ #NoMacDskErr,D0 ; Assume it's for another file system. <01Oct85>
|
|
CMP.W #SigWord,DrSigWord(A5) ; Is it a trustworthy MFS volume? <08Sep85>
|
|
BNE MtVolEr2 ; br if not <01Oct85>
|
|
|
|
; Now do a little more checking before starting to use the data.
|
|
|
|
mv_GotMDB:
|
|
MOVEQ #BadMDBErr,D0 ; in case master directory block is bad
|
|
MOVE.L DrAlBlkSiz(A5),D1 ; make sure this is non-zero, 512 multiple
|
|
BEQ MtVolEr1 ; exit if 0 (shared MFS/TFS exit)
|
|
AND.W #$01FF,D1 ; 512-byte multiple?
|
|
BNE MtVolEr1 ; exit if not (shared MFS/TFS exit)
|
|
|
|
; The MDB seems OK: transfer all master directory info from buffer into VCB.
|
|
|
|
LEA VCBDInfoSt(A2),A1 ; Destination is in VCB
|
|
MOVEQ #VCBDILen,D0 ; Length of MFS/TFS info in MDB
|
|
_BlockMove ; Copy the information
|
|
|
|
MV_GetWPStatus:
|
|
MOVE.L FSQHead,A0 ; A0 -> current request
|
|
MOVE.W VCBVRefNum(A2),IOVRefNum(A0) ; return volume refnum to user
|
|
|
|
LEA Params,A0 ; general purpose I/O param block
|
|
MOVE.W #DrvStsCode,CSCode(A0) ; drive status!
|
|
CLR.B 2+CSParam(A0) ; Clear status byte for return
|
|
_Status ; refnum and drivenum set up by read call
|
|
|
|
MOVEQ #-128,D0 ; $80 mask
|
|
AND.B 2+CSParam(A0),D0 ; WriteProt status get
|
|
MOVE.B D0,VCBAtrb+1(A2) ; write-protect, zeroed consistency status
|
|
_AssumeEq VCBWrProt,7
|
|
|
|
; Now the MFS code diverges from the TFS code.
|
|
|
|
BSR TFSVCBTst ; Is it an MFS volume? <01Oct85>
|
|
BNE MV_GetMFSMap ; Br if so (do the MFS-specific stuff) <01Oct85>
|
|
|
|
LEA DrTInfoSt(A5),A0 ; Advance pointer to additional TFS stuff
|
|
LEA VCBTDInfoSt(A2),A1 ; Point to additional TFS-specific info
|
|
MOVEQ #VCBTDILen,D0 ; Length of additional information
|
|
_BlockMove ; Copy the additional information in
|
|
|
|
MOVE.L VCBAlBlkSiz(A2),D1 ; Pick up allocation block size <22Sep85>
|
|
MOVE.L DrXTFlSize(A5),D0 ; Pick up PEOF of extent B*-Tree <22Sep85>
|
|
JSR DivUp ; Divide (AlBlkSiz MUST BE <64KB!) <22Sep85>
|
|
MOVE.W D0,VCBXTAlBks(A2) ; Store result for use in GetVolInfo <22Sep85>
|
|
MOVE.L DrCTFlSize(A5),D0 ; Pick up PEOF of catalog B*-Tree <22Sep85>
|
|
JSR DivUp ; Compute its allocation similarly <22Sep85>
|
|
MOVE.W D0,VCBCTAlBks(A2) ; And store the result for later use <22Sep85>
|
|
|
|
CLR.W VCBAllocPtr(A2) ; Restart the roving allocation ptr <08Sep85>
|
|
|
|
ADDQ.L #1,VCBWrCnt(A2) ; Compensate for write of MDB on last flush
|
|
|
|
; Try to find two free FCBs for use by the volume control B*-Trees:
|
|
|
|
BSR FindFCB ; Try to find a free FCB (set up D0/D1/A1)
|
|
BNE MtVolErr ; Br if we failed to find one <01Oct85>
|
|
MOVE.W D1,VCBXTRef(A2) ; Set Extents B*-Tree file RefNum
|
|
MOVE.L DrXTFlSize(A5),FCBEOF(A1,D1) ; Set extent tree's LEOF <01Oct85>
|
|
MOVE.L DrXTFlSize(A5),FCBPLen(A1,D1) ; Set extent tree's PEOF <01Oct85>
|
|
|
|
MOVEQ #lenXDR,D0 ; Length of extent record
|
|
LEA DrXTExtRec(A5),A0 ; Point to only XT extent record
|
|
LEA FCBExtRec(A1,D1),A1 ; Point to extent record in FCB <01Oct85>
|
|
_BlockMove ; Copy in the extent record
|
|
|
|
BSR FindFCB ; Try to find another FCB (set up D0/D1/A1)
|
|
BNE MtVolErr ; Punt on error
|
|
MOVE.W D1,VCBCTRef(A2) ; Save catalog file refNum
|
|
MOVE.L DrCTFlSize(A5),FCBEOF(A1,D1) ; Set catalog tree's LEOF <01Oct85>
|
|
MOVE.L DrCTFlSize(A5),FCBPLen(A1,D1) ; Set catalog tree's PEOF <01Oct85>
|
|
|
|
MOVEQ #lenXDR,D0 ; Length of extent record
|
|
LEA DrCTExtRec(A5),A0 ; Point to first catalog extent record
|
|
LEA FCBExtRec(A1,D1),A1 ; Point to extent record in FCB <01Oct85>
|
|
_BlockMove ; Copy in the extent record
|
|
|
|
MOVE.L SysBMCPtr,VCBMAdr(A2) ; Set up the volume bitmap cache
|
|
MOVE.L SysCtlCPtr,VCBCtlBuf(A2) ; Set up the volume control cache
|
|
|
|
; Finish setting up the FCBs for the extent B*-Tree and the catalog B*-Tree:
|
|
|
|
MOVE.W VCBXTRef(A2),D0 ; Get extent-tree refNum
|
|
MOVEQ #FSXTCNID,D1 ; extent-tree file ID
|
|
MOVE.L VCBXTClpSiz(A2),D2 ; clump size
|
|
MOVE.L VCBCtlBuf(A2),A1 ; extent-tree cache
|
|
LEA FXMKeyCmp,A3 ; Key comparison routine for extent tree
|
|
BSR AccessBT ; Set up access to B*-Tree file
|
|
BNE MtChkErr ; Exit on errors <01Oct85>
|
|
|
|
MOVE.W VCBCTRef(A2),D0 ; Get catalog-tree refNum
|
|
MOVEQ #FSCTCNID,D1 ; catalog-tree file ID
|
|
MOVE.L VCBCTClpSiz(A2),D2 ; clump size
|
|
MOVE.L VCBCtlBuf(A2),A1 ; catalog-tree cache
|
|
LEA CMKeyCmp,A3 ; Key comparison routine for catalog tree
|
|
BSR AccessBT ; Set up access to B*-Tree file
|
|
BNE MtChkErr ; Exit on errors <01Oct85>
|
|
|
|
BCLR #VCBAtVOK,VCBAtrb(A2) ; From now until _Unmount <22Aug85>
|
|
; ... the disk is inconsistent <22Aug85>
|
|
BEQ MtCheck ; If it was clear, do the time consuming <01Oct85>
|
|
; disk check
|
|
|
|
; NOTE: The MFS code re-joins this common thread of execution here:
|
|
|
|
CheckRemount:
|
|
MOVE.L jCheckRemount,-(SP) ; jump table entry for vCheckRemount <19Feb87>
|
|
RTS ; go there <19Feb87>
|
|
vCheckRemount ; 'vectored' CheckRemount routine <19Feb87>
|
|
|
|
; Deleted stuff patched out by KillCheckRemountNiceWay in FileMgrPatches.a <SM1>
|
|
|
|
MtVolOK MOVEQ #0,D0 ; no errors
|
|
MtVolDone TST.W D0 ; Any errors encountered?
|
|
BNE.S @1 ; Yes - leave well enough alone, then
|
|
BSR TFSVCBTst ; Mounted a TFS volume?
|
|
BNE.S @1 ; Nope - don't mess with the MDB
|
|
BTST #VCBWrProt,VCBAtrb+1(A2) ; Is volume write protected?
|
|
BNE.S @1 ; If so, don't try to flush the MDB
|
|
BSR MarkVCBDirty ; Make sure it's marked dirty <10Oct85>
|
|
BSR FlushMDB ; Flush the MDB out to mark the volume inconsistent
|
|
@1 BRA CmdDone ; return to command finish
|
|
|
|
MtChkErr MOVE.W D0,HFSDSErr ; Save the error code for debugging <01Oct85>
|
|
MOVEQ #badMDBErr,D0 ; Indicate the MDB is bad for all internal errors
|
|
|
|
; Release any resources allocated so far before exiting with an error:
|
|
|
|
MtVolErr BSR DsposFCBs ; deallocate control file FCBs
|
|
|
|
; The following two exits are shared with MFS mount code . . .
|
|
|
|
MtVolEr1 BSR DsposVBlks ; invalidate any cache blocks for this volume
|
|
MtVolEr2 TST.B NewMount ; only deallocate VCB for new mounts
|
|
BEQ.S @1 ; remount case
|
|
BSR DsposVCB ; new mount -- get rid of VCB
|
|
@0 TST.W D0 ; Check: was this a real error? (or OK Mount) <PWD 07Oct85>
|
|
BLE CmdDone ; Yes - We're all done, then. <PWD 07Oct85>
|
|
MOVE.L FSQHead,A0 ; A0 -> current request <PWD 07Oct85>
|
|
BRA mv_Start ; So start all over again, but don't even THINK <PWD 07Oct85>
|
|
; about the possibility of a ReMount this time. <PWD 07Oct85>
|
|
|
|
; Remount case -- Must zero buffer and map ptrs in old VCB.
|
|
; Restore VCB to its original off-line state (ie clear VCBDrvNum,
|
|
; and move drive number to VCBDRefNum field)
|
|
|
|
@1 ADDA #VCBDrvNum, A2 ; A2 --> drive number field of VCB
|
|
MOVE.W (A2),D3 ; D3 = drive number
|
|
CLR.W (A2)+ ; clear drive number field of VCB
|
|
MOVE.W D3,(A2)+ ; write drv number to VCBDRefNum field
|
|
ADDQ #4,A2 ; A2 --> VCB's buffptr field
|
|
CLR.L (A2)+ ; clear buffptr in VCB
|
|
CLR.L (A2)+ ; clear mapptr in VCB
|
|
BRA.S @0 ; <27Aug85>
|
|
|
|
; Before releasing the volume to the world, do some quick consistency checks
|
|
; (and possibly some patch-ups) on the volume:
|
|
;
|
|
; 1. Make sure the name of the root reflects the volume name in the VCB:
|
|
|
|
MtCheck:
|
|
MOVE.L jMtCheck,-(SP) ; jump table entry for vMtCheck <19Feb87>
|
|
RTS ; go there <19Feb87>
|
|
vMtCheck ; 'vectored' MtCheck routine <19Feb87>
|
|
|
|
|
|
MOVEQ #FSRtDirID,D0 ; Root directory ID
|
|
MOVEQ #0,D2 ; No catalog hint
|
|
MOVE.L D2,A0 ; Nil CName
|
|
JSR CMGetCN ; Look up the root directory
|
|
BNE.S MtChkErr ; Punt on errors
|
|
MOVEQ #0,D0 ; Clear all unused bytes
|
|
LEA ckrCName(A0),A1 ; Point to CName in key
|
|
MOVE.B (A1)+,D0 ; Pick up length byte
|
|
SWAP D0 ; Stash 'second' string length
|
|
LEA VCBVN(A2),A0 ; Source is volume name
|
|
MOVE.B (A0)+,D0 ; Pick up 'first' string length
|
|
SWAP D0 ; Put things in order for _CmpString
|
|
_CmpString ,MARKS,CASE ; EVERYTHING counts here...
|
|
BEQ.S BMScan ; If this is OK, check the rest of the catalog
|
|
|
|
; the names don't match, check length of volume name
|
|
|
|
SUBQ.L #1,A1 ; Point back to root name again <16Sep86>
|
|
SUBQ.L #1,A0 ; Point back to volume name again <16Sep86>
|
|
MOVEQ #0,D0 ; Pick up length byte <02Oct86>
|
|
MOVE.B (A0),D0 ; <02Oct86>
|
|
BEQ.S @2 ; use root name if zero -> <16Sep86>
|
|
CMPI.W #VCBMaxNam,D0 ; check if length greater than max <16Sep86>
|
|
BLE.S @1 ; br if not -> <16Sep86>
|
|
MOVE.B #VCBMaxNam,(A0) ; truncate it to max length <16Sep86>
|
|
|
|
; the length of volume name is ok, rename the root directory
|
|
|
|
@1 MOVEQ #FSRtDirID,D0 ; root DirID <16Sep86>
|
|
MOVEA.L A0,A1 ; volume name is new name <16Sep86>
|
|
SUBA.L A0,A0 ; use only the DirID to identify root <16Sep86>
|
|
MOVEQ #0,D2 ; no hint <16Sep86>
|
|
JSR CMRenameCN ; rename the root directory <16Sep86>
|
|
BNE.S MtChkErr ; punt on errors <16Sep86>
|
|
BRA.S BMScan ; continue with bit map check <16Sep86>
|
|
|
|
; the length of the volume name is zero, check root name length
|
|
|
|
@2 MOVEQ #0,D0 ; Pick up length byte <02Oct86>
|
|
MOVE.B (A1),D0 ; <02Oct86>
|
|
BEQ MtChkErr ; give up if root name is zero also <16Sep86>
|
|
CMPI.W #VCBMaxNam,D0 ; check if length greater than max <16Sep86>
|
|
BLE.S @3 ; br if not -> <16Sep86>
|
|
MOVEQ #VCBMaxNam,D0 ; truncate it to max length <16Sep86>
|
|
|
|
; the root name length is ok, change volume name to root name
|
|
|
|
@3 MOVE.B D0,(A0)+ ; move in the length byte <16Sep86>
|
|
SUBQ.W #1,D0 ; adjust D0 for DBRA <16Sep86>
|
|
ADDQ.L #1,A1 ; position pass root name length byte <16Sep86>
|
|
@4 MOVE.B (A1)+,(A0)+ ; move in <16Sep86>
|
|
DBRA D0,@4 ; .. the name <16Sep86>
|
|
|
|
; EXG A0,A1 ; Sigh - CMRename likes 'em differently <16Sep86>
|
|
; MOVEQ #FSRtParID,D0 ; This directory exists in the root parent <16Sep86>
|
|
; <Use catalog hint still in D2>
|
|
; JSR CMRenameCN ; Change the name <16Sep86>
|
|
; BNE MtChkErr ; Punt on errors <16Sep86>
|
|
|
|
; 2. Make sure the bitmap reflects the allocation status of all extent records:
|
|
|
|
BMScan: MOVE.L FCBsPtr,A1 ; Point to FCB table <07Oct85>
|
|
|
|
MOVE.W VCBXTRef(A2),D1 ; Pick up extent B*-tree refNum <07Oct85>
|
|
LEA FCBExtRec(A1,D1),A0 ; Point to extent record there <07Oct85>
|
|
BSR BMChk ; Check this extent record <07Oct85>
|
|
|
|
MOVE.W VCBCTRef(A2),D1 ; Pick up catalog B*-Tree refNum <07Oct85>
|
|
LEA FCBExtRec(A1,D1),A0 ; Point to extent record for B*-Tree <07Oct85>
|
|
BSR BMChk ; Check this extent's allocation status <07Oct85>
|
|
|
|
; Start by scanning the remainder of the catalog to verify all extent
|
|
; records in the catalog:
|
|
|
|
MOVEQ #FSRtDirID,D0 ; Root directory ID
|
|
; Use catalog hint in D2
|
|
SUBA.L A0,A0 ; Generate a nil CName
|
|
JSR CMGetCN ; Look up the root directory
|
|
BNE MtChkErr ; Punt on errors
|
|
|
|
MOVEA.L FCBsPtr,A1 ; Point to the FCBs
|
|
MOVE.W VCBCTRef(A2),D1 ; Pick up the catalog refNum
|
|
|
|
; Before starting a scan of the catalog, make a conservative estimate of the
|
|
; upper limit of B*-Tree records that could conceivably be encountered in a
|
|
; scan of all leaf nodes by dividing the catalog's PEOF by the size of the
|
|
; smalles CNode (a directory entry):
|
|
|
|
MOVE.L FCBPLen(A1,D1),D0 ; Pick up the catalog size in bytes
|
|
LSR.L #6,D0 ; divide by 64 (less than smallest record size)
|
|
MOVE.L D0,D2 ; D2 = max. number of CNodes possible
|
|
|
|
MOVEQ #FSUsrCNID-1,D4 ; Reset largest CNID found <29Aug85>
|
|
MOVEQ #0,D3 ; Clear inconsistency flag
|
|
MOVEQ #0,D5 ; Clear file count
|
|
MOVEQ #0,D6 ; Clear directory count
|
|
MOVEQ #0,D7 ; Clear root content counts (high & low)
|
|
CTScan: SUBQ.L #1,D2 ; Count down by ones
|
|
BLT MtChkErr ; No mounting on loop errors <08Sep85>
|
|
|
|
@10 MOVE.W VCBCTRef(A2),D0 ; Catalog tree refNum
|
|
MOVEQ #1,D1 ; Get first record following current record
|
|
MOVE.L D2,-(A6) ; Save record count across call
|
|
JSR BTGetRecord ;
|
|
MOVE.L (A6)+,D2 ; Restore record count, destroying hint.
|
|
TST.W D0 ; Check for error on BTGetRecord
|
|
BNE.S @90 ; Punt on errors
|
|
CMP.B #cdrDirRec,cdrType(A1) ; Is this a directory?
|
|
BNE.S @25 ; If not, check for files
|
|
ADDQ.L #1,D6 ; Bump the total directory count
|
|
CMP.L #FSRtDirID,ckrParID(A0) ; Is this directory in the root?
|
|
BNE.S @15 ; If not, nothing special
|
|
SWAP D7 ; Get access to the high word
|
|
ADDQ.W #1,D7 ; Bump the root directory count
|
|
SWAP D7 ; And store it back.
|
|
@15 CMP.L dirDirID(A1),D4 ; Is this DirID bigger than cur. maximum?
|
|
BHS.S CTScan ; If not, keep looking
|
|
MOVE.L dirDirID(A1),D4 ; Otherwise, retain this new high
|
|
BRA.S CTScan ; And ignore directories otherwise
|
|
|
|
@25 CMP.B #cdrFilRec,cdrType(A1) ; Is this a file?
|
|
BNE.S CTScan ; If not, just keep on looking
|
|
ADDQ.L #1,D5 ; Bump the total file count
|
|
CMP.L #FSRtDirID,ckrParID(A0) ; Is this directory in the root?
|
|
BNE.S @30 ; If not, nothing special
|
|
ADDQ.W #1,D7 ; Bump the root file count
|
|
@30 CMP.L filFlNum(A1),D4 ; Is this file number a new maximum?
|
|
BCC.S @50 ; If not, just check its allocation
|
|
MOVE.L filFlNum(A1),D4 ; Otherwise, remember this peak
|
|
|
|
; Check the blocks allocated to this file (both forks):
|
|
|
|
@50 LEA filExtRec(A1),A0 ; Point to extent record for data fork
|
|
BSR BMChk ; Check its allocation status <07Oct85>
|
|
LEA filRExtRec(A1),A0 ; Point to extent record for resource fork
|
|
BSR BMChk ; Check its allocation status <07Oct85>
|
|
BRA.S CTScan ; Go for the next record
|
|
|
|
@90 CMP.W #BTNotFound,D0 ; Was record not found?
|
|
BNE MtChkErr ; Punt on other errors
|
|
|
|
VCBChk: CMP.L VCBNxtCNID(A2),D4 ; Is the maximum found in scan consistent?
|
|
BCS.S @10 ; If so, that's nice [expected]
|
|
ADDQ.L #1,D4 ; Otherwise, THIS is the next CNode ID
|
|
MOVE.L D4,VCBNxtCNID(A2) ; Record the new maximum
|
|
BSET #0,VCBAtrb+1(A2) ; Mark error in VCB attributes
|
|
MOVEQ #-1,D3 ; Mark a scan error
|
|
|
|
@10 CMP.L VCBFilCnt(A2),D5 ; Check total number of files on volume
|
|
BEQ.S @20 ; If same, continue
|
|
MOVE.L D5,VCBFilCnt(A2) ; Otherwise, fix the inconsistency
|
|
BSET #1,VCBAtrb+1(A2) ; Mark error in VCB attributes
|
|
MOVEQ #-1,D3 ; But mark the scan error
|
|
|
|
@20 CMP.L VCBDirCnt(A2),D6 ; Check total number of directories on volume
|
|
BEQ.S @30 ; If same, continue
|
|
MOVE.L D6,VCBDirCnt(A2) ; Fix the inconsistency
|
|
BSET #1,VCBAtrb+1(A2) ; Mark the error in VCB attributes
|
|
MOVEQ #-1,D3 ; Mark the scan error
|
|
|
|
@30 CMP.W VCBNmFls(A2),D7 ; Check the number of files in the root
|
|
BEQ.S @40 ; If that's OK, continue
|
|
MOVE.W D7,VCBNmFls(A2) ; Otherwise, overwrite the VCB info.
|
|
BSET #1,VCBAtrb+1(A2) ; Mark error in VCB attributes
|
|
MOVEQ #-1,D3 ; And mark a scan error
|
|
|
|
@40 SWAP D7 ; Get the root directory count in low word
|
|
CMP.W VCBNmRtDirs(A2),D7 ; Check the number of root directories
|
|
BEQ.S @90 ; Continue if all seems well
|
|
MOVE.W D7,VCBNmRtDirs(A2) ; Otherwise, update the VCB info.
|
|
BSET #1,VCBAtrb+1(A2) ; Mark error in VCB attributes
|
|
MOVEQ #-1,D3 ; And mark a scan error
|
|
|
|
@90
|
|
|
|
; Next, scan the extent tree to make sure all extent records are actually
|
|
; marked as allocated:
|
|
|
|
XTScan:
|
|
|
|
; Before starting a scan of the extenbt tree, make a conservative estimate of the
|
|
; upper limit of B*-Tree records that could conceivably be encountered in a
|
|
; scan of all leaf nodes by dividing the catalog's PEOF by the size of an extent
|
|
; record:
|
|
|
|
MOVEA.L FCBsPtr,A1 ; Point to the FCB array
|
|
MOVE.W VCBXTRef(A2),D1 ; Pick up the extent tree refNum
|
|
MOVE.L FCBPLen(A1,D1),D0 ; Pick up the extent tree size in bytes
|
|
LSR.L #4,D0 ; divide by 16 (less than smallest record size)
|
|
MOVE.L D0,D5 ; D5 = max. number of extent records
|
|
|
|
MOVE.W VCBXTRef(A2),D0 ; Extent tree refNum
|
|
SUB.W #lenXKR,A6 ; Allocate an extent tree key on the stack
|
|
MOVEA.L A6,A0 ; Set up pointer to extent key
|
|
MOVE.W #$0700,xkrKeyLen(A0); Set up key length & fork type
|
|
CLR.L xkrFNum(A0) ; Clear file number in key
|
|
CLR.W xkrFABN(A0) ; Clear starting allocation block in key
|
|
MOVEQ #0,D2 ; Clear B*-Tree hint
|
|
JSR BTSearch ; Look for this key [which cannot exist]
|
|
ADD.W #lenXKR,A6 ; Deallocate key from stack
|
|
MOVEQ #0,D1 ; Select record right of insertion point
|
|
@10 SUBQ.L #1,D5 ; Count down by one
|
|
BLT MtChkErr ; No mounting on loop errors <08Sep85>
|
|
|
|
@20 MOVE.W VCBXTRef(A2),D0 ; Set up extent tree RefNum again
|
|
JSR BTGetRecord ; Try to get it
|
|
BNE.S @90 ; Stop on errors
|
|
|
|
; Check the allocation status of this extent record:
|
|
|
|
MOVEA.L A1,A0 ; Point to extent record
|
|
BSR.S BMChk ; Check the allocation status <07Oct85>
|
|
MOVEQ #1,D1 ; Set up to get next record
|
|
@50 BRA.S @10 ; And go for it
|
|
|
|
@90 CMP.W #BTNotFound,D0 ; No more records to be found?
|
|
BNE MtChkErr ; If not, that's serious trouble
|
|
|
|
; Finally, refigure the free block count by counting all zero bits in allocation map
|
|
|
|
JSR UpdateFree ; VSM routine does this for us . . . <08Sep85>
|
|
BRA CheckRemount ; This mount is OK: Check for remount <14Oct85>
|
|
|
|
BMChk
|
|
MOVE.L jBMChk,-(SP) ; jump table entry for vBMChk <27Oct86>
|
|
RTS ; go there <27Oct86>
|
|
vBMChk ; 'vectored' BMChk routine <27Oct86>
|
|
|
|
MOVE.L (SP)+,-(A6) ; Save return address <09Oct85>
|
|
BSR CVFlgs ; Can we write the volume? <18Oct85>
|
|
BNE.S @10 ; If not, no point fixing the bitmap <18Oct85>
|
|
JSR BlkChk ; Check the allocation status <07Oct85>
|
|
BEQ.S @10 ; Continue if all was well <07Oct85>
|
|
MOVEQ #-1,D3 ; Make a note of the inconsistency <07Oct85>
|
|
BSET #2,VCBAtrb+1(A2) ; Mark error in allocation map <07Oct85>
|
|
@10 MOVE.L (A6)+,-(SP) ; Restore original return address <09Oct85>
|
|
RTS ; <07Oct85>
|
|
|
|
IF hasManEject THEN ; <SM7> <BH 03Aug93>
|
|
;--------------------------------------------------------------------------------------
|
|
; Routine: SetVCBManEject
|
|
; Input: A2 = VCB ptr
|
|
; Called by: MountVol
|
|
; Function: Sets or clears the manual-eject bit in the flags word of the input VCB
|
|
; based on the type of the drive indicated by vcbDrvNum. All registers
|
|
; are preserved. The manual-eject flag should only be changed at MountVol
|
|
; time.
|
|
;--------------------------------------------------------------------------------------
|
|
SetVCBManEject
|
|
MOVEM.L A0/D0,-(SP) ; save regs
|
|
MOVE.W vcbDrvNum(A2),D0 ; get drive num
|
|
MOVEA.L DrvQHdr+qHead,A0 ; get first DQE
|
|
@check CMP.W dqDrive(A0),D0 ; match?
|
|
BEQ.S @found ; yep: go set the flag
|
|
MOVEA.L qLink(A0),A0 ; no: check the next one
|
|
BRA.S @check
|
|
@found MOVE.W vcbFlags(A2),D0 ; get flags word
|
|
BTST #dqManEjBit,dqInstall(A0) ; is this a manual-eject drive?
|
|
BEQ.S @no ; no: clear the flag
|
|
BSET #vcbManEjBit,D0 ; yes: set it
|
|
BRA.S @exit
|
|
@no BCLR #vcbManEjBit,D0 ; clear the flag
|
|
@exit MOVE.W D0,vcbFlags(A2) ; store flags
|
|
MOVEM.L (SP)+,A0/D0 ; restore regs
|
|
RTS ; goodbye
|
|
ENDIF
|
|
|
|
;________________________________________________________________________________
|
|
;
|
|
; Routines: DsposFCBs, DsposVCB, DsposVBlks
|
|
; Function: Shared routines for tearing down volume structures.
|
|
;________________________________________________________________________________
|
|
|
|
DsposFCBs MOVEM.L D0-D1/A1,-(SP) ; preserve all regs <01Oct85>
|
|
MOVEA.L FCBsPtr,A1 ; Point to FCB table <01Oct85>
|
|
|
|
MOVE.W VCBXTRef(A2),D1 ; Get Extent B*-Tree refNum
|
|
BEQ.S @1 ; br if unallocated
|
|
CLR.L FCBFlNm(A1,D1) ; Clear file number to FCB as unused <01Oct85>
|
|
|
|
@1 MOVE.W VCBCTRef(A2),D1 ; Get catalog refnum
|
|
BEQ.S @2 ; If zero, it's unallocated
|
|
CLR.L FCBFlNm(A1,D1) ; Clear file number to FCB as unused <01Oct85>
|
|
|
|
@2 MOVEM.L (SP)+,D0-D1/A1 ; restore all regs <01Oct85>
|
|
RTS ;
|
|
|
|
DsposVCB MOVE.L D0,-(SP) ; preserve error code
|
|
|
|
; Close any working directories left open for this volume (the VCB is about to
|
|
; disappear):
|
|
|
|
BSR Gt1stWDVMatch ; sets up A1, D1 <28Aug85>
|
|
@1 BNE.S @2 ; br if no more WDCBs <28Aug85>
|
|
CLR.L WDVCBPtr(A1,D1) ; free the WDCB <28Aug85>
|
|
CLR.L WDDirID(A1,D1) ; <30Aug85>
|
|
BSR GtNxtWDVMatch ; <28Aug85>
|
|
BRA.S @1 ; <28Aug85>
|
|
|
|
@2 MOVE.L A2,A0 ; dequeue this VCB
|
|
LEA VCBQHdr,A1 ; ptr to VCB queue header
|
|
JSR DequeueTrap ; unlink this VCB from the VCB queue
|
|
|
|
CMP.L DefVCBPtr,A2 ; did we unmount our default? <30Aug85>
|
|
BNE.S @3 ; br if not <30Aug85>
|
|
CLR.L DefVCBPtr ; if so, no more default <30Aug85>
|
|
CLR.W DefVRefNum ; And no more default VRefNum <30Aug85>
|
|
|
|
@3 _DisposPtr ; dispose VCB and buffer memory <30Aug85>
|
|
|
|
DsposExit MOVE.L (SP)+,D0 ; restore error code
|
|
RTS
|
|
|
|
; DsposVBlks trashes all cache blocks for a given volume (specified by A2=VCB ptr).
|
|
; It is called on mount errs and when unmounting a volume.
|
|
|
|
DsposVBlks MOVE.L A1,-(SP) ; save all regs <30Aug85>
|
|
MOVE.L SysBMCPtr,A1 ; System-wide bitmap cache pointer <30Aug85>
|
|
JSR TrashVBlks ; A2=VCB ptr <30Aug85>
|
|
MOVE.L SysVolCPtr,A1 ; System-wide volume cache pointer <30Aug85>
|
|
JSR TrashVBlks ; A2=VCB ptr <30Aug85>
|
|
MOVE.L SysCtlCPtr,A1 ; System-wide control cache pointer <30Aug85>
|
|
JSR TrashVBlks ; A2=VCB ptr <30Aug85>
|
|
MOVE.L (SP)+,A1 ; <30Aug85>
|
|
RTS ; <30Aug85>
|
|
|
|
;________________________________________________________________________________
|
|
;
|
|
; Routine: FindFCB
|
|
;
|
|
; Arguments: D1.W (out) - FCB index (suitable for use as File RefNum).
|
|
; A1.L (out) - FCB ptr
|
|
; D0.W (out) - TMFOErr or 0 if ok.
|
|
; All other regs preserved.
|
|
;
|
|
; Function: Find an unused FCB
|
|
;
|
|
; Modification history:
|
|
; 22-Jul-85 PWD Changed to skip first FCB (#2), left free for system file.
|
|
; <01Oct85> LAK Rewrote to use Gt1stFCB, GtNxtFCB routines, and to return A1/D0/D1.
|
|
;________________________________________________________________________________
|
|
|
|
FindFCB:
|
|
BSR Gt1stFCB ; get (A1,D1) pointing to first FCB <01Oct85>
|
|
BRA.S @2 ; skip first FCB (save for System file) <01Oct85>
|
|
|
|
@1 TST.L FCBFlNm(A1,D1) ; FCB unused? <01Oct85>
|
|
BNE.S @2 ; br if so <01Oct85>
|
|
MOVEQ #-1,D0 ; get -1 <01Oct85>
|
|
MOVE.L D0,FCBFlNm(A1,D1) ; Found a free one: mark as in-use <01Oct85>
|
|
MOVEQ #0,D0 ; no error <01Oct85>
|
|
BRA.S @3 ; <01Oct85>
|
|
|
|
@2 BSR GtNxtFCB ; get next one until we run out <01Oct85>
|
|
BCS.S @1 ; <01Oct85>
|
|
MOVEQ #TMFOErr,D0 ; too many files open <01Oct85>
|
|
|
|
@3 RTS ; <01Oct85>
|
|
|
|
|
|
;________________________________________________________________________________
|
|
;
|
|
; Routine: AccessBT
|
|
;
|
|
; Function: Create an access path for a B*-Tree file:
|
|
; 1. Initialize the FCB
|
|
; 2. Attach a B*-Tree control block
|
|
;
|
|
; Inputs:
|
|
; D0.W - File FCB
|
|
; D1.L - File ID
|
|
; D2.L - File clump size
|
|
; A1 - Cache buffer
|
|
; A2 - VCB pointer
|
|
; A3 - Address of key comparison routine
|
|
;
|
|
; Outputs:
|
|
; D0.W - I/O result from BTOpen
|
|
;________________________________________________________________________________
|
|
|
|
AccessBT: MOVE.L (SP)+,-(A6) ; Save return address
|
|
MOVEM.L D3/A0,-(A6) ; Save scratch registers
|
|
MOVEA.L FCBsPtr,A0 ; Point to FCB table
|
|
LEA 0(A0,D0.W),A0 ; Point to FCB itself
|
|
CLR.W FCBFlags(A0) ; Clear flag bytes
|
|
CLR.W FCBSBlk(A0) ; Start block is undefined
|
|
CLR.L FCBCrPs(A0) ; Current position is undefined
|
|
MOVE.L D1,FCBFlNm(A0) ; Set file ID
|
|
MOVE.L A2,FCBVPtr(A0) ; Set VCB pointer
|
|
MOVE.L D2,FCBClmpSize(A0) ; Set File Clump Size
|
|
MOVEA.L A3,A0 ; Key comparison routine
|
|
JSR BTOpen ; Open file for B*-Tree access
|
|
MOVEM.L (A6)+,D3/A0 ; Restore registers
|
|
MOVE.L (A6)+,-(SP) ; Restore return address
|
|
TST.W D0
|
|
RTS
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: FindDrive
|
|
; Arguments: D2.W (input) -- drive number
|
|
; D1.W (output) -- driver refnum for this drive number
|
|
; D2.W (output) -- drive number
|
|
; D0.W (output) -- error code (no such drive)
|
|
; A3.L (output) -- pointer to DQE for drive in question
|
|
; All other registers are preserved.
|
|
; Calls: QWordSearch
|
|
; Called By: Eject,MountVol
|
|
; Function: Given a drive number, this routine returns the RefNum
|
|
; for the driver by searching the system drive queue.
|
|
;
|
|
; Modification History:
|
|
; 06 Dec 82 LAK New today.
|
|
; 13 Jan 83 LAK Removed block offset - now returns drive number in D2
|
|
; 01 Jun 83 LAK Checks added DQFSID field, reporting ExtFSErr if nonzero
|
|
; 25 Apr 85 PWD Changed to return DQE pointer in A3 for use in Eject.
|
|
;_______________________________________________________________________
|
|
|
|
FindDrive:
|
|
MOVE.L jFindDrive,-(SP) ; jump table entry for vFindDrive <19Feb87>
|
|
RTS ; go there <19Feb87>
|
|
vFindDrive ; 'vectored' FindDrive routine <19Feb87>
|
|
MOVE.L A0,-(SP) ; preserve A0
|
|
MOVE.W D2,D0 ; search using this drive number as the key
|
|
LEA DrvQHdr,A0 ; search the queue of drive numbers
|
|
MOVEQ #DQDrive,D1 ; for drive number
|
|
BSR QWordSearch
|
|
BNE.S @2 ; exit if not found
|
|
|
|
MOVEA.L A0,A3 ; Return pointer to DQE
|
|
MOVE DQRefNum(A0),D1 ; return refnum
|
|
MOVE.W DQFSID(A0),D0 ; is it for us?
|
|
BEQ.S @1 ; br if so
|
|
MOVEQ #ExtFSErr,D0 ; otherwise, report an error
|
|
|
|
@1 MOVEA.L (SP)+,A0 ; restore A0
|
|
RTS
|
|
|
|
@2 MOVEQ #NSDrvErr,D0 ; no such drive number
|
|
BRA.S @1
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: OffLine
|
|
; Arguments:
|
|
; Calls:
|
|
; Called By:
|
|
; Function:
|
|
;
|
|
; Modification History:
|
|
;
|
|
; In order to make the disk switch hook run without moving memory, we need
|
|
; to leave the btree control files (catalog and extents) open when putting
|
|
; a volume offline, so that the subsequent _Mount call won't have to allocate
|
|
; a new btree control block.
|
|
;
|
|
; 5 Jul 84 GSS Added this call to the TFS code
|
|
;_______________________________________________________________________
|
|
; Rolled in NoCloseOnOffline patch from FileMgrPatches.a <SM1>
|
|
OffLine:
|
|
BSR FSQueueSync ; wait until all current calls are done <SM1>
|
|
|
|
ST NoEject ; NoEject.B = -1: mark vol. offline but
|
|
; don't eject the diskette
|
|
BRA Eject1 ; share code with Eject
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: Eject
|
|
; Arguments: A0 (input) -- pointer to volume parameter block, uses IODrvNum,
|
|
; IOFileName
|
|
; D0 (output) -- error code
|
|
; This call is executed synchronously until the eject call is
|
|
; actually made.
|
|
; Calls: _FlushVol,_Control
|
|
;
|
|
; Function: The volume in the drive is flushed and its block map and buffer
|
|
; block are deallocated. A control call to the disk driver
|
|
; is made to eject the diskette.
|
|
;
|
|
; Modification History:
|
|
; 06-Dec-82 LAK New today.
|
|
; 13-Jan-83 LAK Disk control call now uses drive number parameter. Completion
|
|
; routine is now just CmdDone.
|
|
; 01-Jun-83 LAK Changed to just flush the volume before ejecting; VCB
|
|
; drive number and driver number are zeroed.
|
|
; 05-Jul-84 GSS Patched from MSFileFix code
|
|
; 12-Feb-85 PWD Split off MFS code and adapted for use in Turbo FS.
|
|
; 25-Apr-85 PWD Changed to leave non-ejectable volumes online.
|
|
; 26-Jun-85 PWD Changed to not call driver for non-ejectable disks
|
|
; <30Aug85> LAK Changed to force Eject to be synchronous since FlushMDB must be
|
|
; done BEFORE closing of volume B-tree files. Why not use
|
|
; a separate parameter block for Eject so we can return immediately?
|
|
; <14Oct85> PWD Added DumpCaches routine for use by MountVol on remount.
|
|
; <28Oct85> PWD Changed to pass control call to drivers anyway if 64 <= DIP <= 127
|
|
; mung VCB as for _Offline call for these drivers. Changed to
|
|
; interpret NoEject as tri-state flag: -1[offline], 0[eject], or
|
|
; +1 [offline w. special eject control call].
|
|
;
|
|
; Notes:
|
|
; - CmdDone gets result code from D0 and assumes it is being called when the
|
|
; first routine on the queue is satisfied, so it all works . . .
|
|
; - Should the diskette still be ejected if the flush does not work?
|
|
; Should directory writes be verified for paranoid users?
|
|
;
|
|
;_______________________________________________________________________
|
|
; Rolled in NoCloseOnEject patch from FileMgrPatches.a <SM1>
|
|
|
|
; DumpCaches is called by MountVol when a remount is detected to flush out any <14Oct85>
|
|
; changes the consistency check may have brought [part. in the bitmap cache], <14Oct85>
|
|
; and trash the cache blocks marked with the now-defunct VRefNum/VCBPtr <14Oct85>
|
|
; <14Oct85>
|
|
; Called by: MountVol <14Oct85>
|
|
|
|
DumpCaches: MOVE.L (SP)+,-(A6) ; Save return address across ,ASYNC I/O <14Oct85>
|
|
MOVEM.L A1/D1-D2,-(A6) ; Free same scratch registers as below <24Oct85>
|
|
CLR.B FlushOnly ; Trash cache blocks after flushing <14Oct85>
|
|
BRA.S flVCaches ; Go flush the cache buffers <14Oct85>
|
|
|
|
; FlushBuffers is a code-sharing routine used by Eject and Flush/UnMountVol to flush the
|
|
; MDB (marking the volume consistent for Eject and UnMount), and flushing (and
|
|
; closing for Eject and UnMount) the volume control files . . . it likes to have
|
|
; the FlushOnly flag and A2 set appropriately on entry . . . It also flushes all buffers
|
|
; (and invalidates all cache blocks for the volume if FlushOnly=0).
|
|
;
|
|
; Called By: Eject, FlushVol, MFSFlush
|
|
|
|
FlushBuffers: ; <01Oct85>
|
|
MOVE.L (SP)+,-(A6) ; Save return address for ,ASYNC calls <29Aug85>
|
|
MOVEM.L A1/D1-D2,-(A6) ; Save all regs except D0 <24Oct85>
|
|
BSR TFSVCBTst ; Is it an MFS volume? <01Oct85>
|
|
BNE.S flVCaches ; Br if so (just flush caches) <01Oct85>
|
|
|
|
TST.B FlushOnly ; Just flushing? <29Aug85>
|
|
BNE.S @1 ; Br if so <29Aug85>
|
|
BSR CVFlgs ; Is volume write protected? <01Oct85>
|
|
BNE.S @1 ; If so, don't try to mark it dirty <01Oct85>
|
|
BSET #VCBAtVOK,VCBAtrb(A2) ; Indicate vol was unmounted ok <29Aug85>
|
|
BSR MarkVCBDirty ; mark VCB dirty so it will be written <10Oct85>
|
|
@1 JSR FlushMDB ; Go flush the VCB info BEFORE close <29Aug85>
|
|
|
|
MOVEA.L FCBsPtr,A1 ; Point to FCB array <29Aug85>
|
|
|
|
MOVE.W VCBCTRef(A2),D1 ; Catalog B*-Tree file refnum <29Aug85>
|
|
BSR FClose ; Close the file itself <29Aug85>
|
|
BNE.S flBufExit ; Punt on errors <29Aug85>
|
|
TST.B FlushOnly ; Just flushing? <29Aug85>
|
|
BNE.S @2 ; If so, the FCB's still 'live' <29Aug85>
|
|
CLR.W VCBCTRef(A2) ; Indicate it's gone <29Aug85>
|
|
|
|
@2 MOVE.W VCBXTRef(A2),D1 ; Extent B*-Tree file refnum <29Aug85>
|
|
BSR FClose ; Close the file itself <29Aug85>
|
|
BNE.S flBufExit ; Rats - and we were SO CLOSE... <29Aug85>
|
|
TST.B FlushOnly ; Just flushing? <29Aug85>
|
|
BNE.S flVCaches ; If so, there's still data in the FCB <29Aug85>
|
|
CLR.W VCBCTRef(A2) ; It's a goner now... <29Aug85>
|
|
|
|
; Flush the volume caches (this code is shared with MFSFlush)
|
|
|
|
flVCaches:
|
|
MOVEQ #0,D1 ; Clear options byte (we'll trash later)
|
|
ST CacheFlag ; Yes, REALLY flush . . . <05Sep85>
|
|
|
|
MOVE.L SysBMCPtr,A1 ; System-wide bitmap cache pointer <30Aug85>
|
|
MOVE.W VCBVRefNum(A2),D0 ; Volume refnum <21Sep85>
|
|
JSR FlushCache ; A2=VCB ptr <30Aug85>
|
|
|
|
MOVE.L SysCtlCPtr,A1 ; System-wide control cache pointer <30Aug85>
|
|
MOVE.W VCBVRefNum(A2),D0 ; Volume refnum <21Sep85>
|
|
JSR FlushCache ; A2=VCB ptr <30Aug85>
|
|
|
|
MOVE.L SysVolCPtr,A1 ; System-wide volume cache pointer <30Aug85>
|
|
MOVE.W VCBVRefNum(A2),D0 ; Volume refnum <21Sep85>
|
|
JSR FlushCache ; A2=VCB ptr <30Aug85>
|
|
|
|
TST.B FlushOnly ; Just flushing? <30Aug85>
|
|
BNE.S flBufOK ; If so, that's all we ask <30Aug85>
|
|
BSR DsposVBlks ; Otherwise, trash blocks for A2 volume <30Aug85>
|
|
|
|
flBufOK MOVEQ #0,D0 ; it's cool <29Aug85>
|
|
|
|
flBufExit MOVEM.L (A6)+,A1/D1-D2 ; Restore regs <24Oct85>
|
|
MOVE.L (A6)+,-(SP) ; Restore the return address <29Aug85>
|
|
TST.W D0 ; <29Aug85>
|
|
RTS ; <29Aug85>
|
|
|
|
EjectTrap:
|
|
BSR FSQueueSync ; wait until all current calls are done <SM1>
|
|
|
|
CLR.B NoEject ; want to really eject here . . .
|
|
|
|
Eject1:
|
|
BSR DtrmV3 ; check name, drive number, etc. <30Aug85>
|
|
BNE.S @1 ; br if drive not mounted (why flush?) <30Aug85>
|
|
BSR CkExtFS ; see if it's for an external fs <30Aug85>
|
|
BNE.S EjectDone ; exit if so <30Aug85>
|
|
BRA.S ejectMnted ; otherwise, go the 'mounted volume' route <30Aug85>
|
|
|
|
@1 MOVE.W IOVDrvNum(A0),D2 ; drive number
|
|
|
|
ejectDrvNum BSR FindDrive ; get disk driver refnum in D1
|
|
BNE.S ejectDone ; exit if no mapping for this drive <29Aug85>
|
|
TST.B NoEject ; REALLY eject this thing?
|
|
BEQ EjectIt ; OK, OK; it's going already...
|
|
|
|
ejectDone BRA CmdDone ; we're done . . . <29Aug85>
|
|
|
|
ejectMnted LEA VCBDrvNum(A2),A1
|
|
MOVE.W (A1),D2 ; on-line, non-ejected?
|
|
BNE.S @0 ; br if so <29Aug85>
|
|
|
|
MOVE.W 2(A1),D2 ; is it already ejected?
|
|
BPL.S ejectDone ; just exit if so
|
|
TST.B NoEject ; no eject?
|
|
BNE.S ejectDone ; br if so (it's already offline . . .) <29Aug85>
|
|
|
|
NEG.W D2 ; get non-ejected offline disk's drive number
|
|
NEG.W 2(A1) ; mark it now ejected . . .
|
|
BRA.S ejectDrvNum ; and eject it (pass D2=drive number)
|
|
; NOTE: the previous OffLine call would have marked
|
|
; a TFS disk consistent.
|
|
|
|
; OK, it's on-line and not ejected . . . so make it offline and eject if appropriate . . .
|
|
|
|
@0 BSR FindDrive ; Find DQE from drive number in D2
|
|
BNE.S ejectDone ; Punt if can't be found
|
|
TST.B NoEject ; Just an _Offline call? <28Oct85>
|
|
BNE.S @5 ; Yes - don't try harder than needed <28Oct85>
|
|
CMP.B #8,DQDIP(A3) ; Check drive ejectability: <29Aug85>
|
|
BLT.S @5 ; Skip if it's ejectable <28Oct85>
|
|
ST NoEject ; If DQDIP > 8, it's non-ejectable <28Oct85>
|
|
CMP.B #64,DQDIP(A3) ; Send a _Control call anyway? <28Oct85>
|
|
BLT.S @5 ; No need - we're set as is. <28Oct85>
|
|
MOVE.B #1,NoEject ; If >64, call the driver anyway. <28Oct85>
|
|
|
|
@5 ST FlushOnly ; only flushing (don't close . . .) <11Sep85>
|
|
BSR FlushVFiles ; flush all files on this volume <11Sep85>
|
|
|
|
BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
|
|
BNE.S @10 ; Nope.
|
|
|
|
; note that the following line is the opposite of the OLD code. We only want to flush
|
|
; these files, since _Unmount will close them later. However, we do want to mark the
|
|
; vcb consistent as it goes offline.
|
|
BSR CVFlgs ; Is volume write protected? <31>
|
|
BNE.S @1 ; If so, don't try to mark it dirty <31>
|
|
BSET.B #vcbAtVOK,vcbAtrb(a2) ; Indicate vol was unmounted ok <31>
|
|
BSR MarkVCBDirty ; mark VCB dirty so it will be written <31>
|
|
@1 BSR FlushMDB ; Go flush the VCB info BEFORE flushing <31>
|
|
|
|
ST.B FlushOnly ; just flush the control files
|
|
BSR FlushBuffers ; and flush MDB as 'consistent' <01Oct85>
|
|
BRA.S ejectMark ; now go mark it . . . <29Aug85>
|
|
|
|
; FlushOnly is still set for MFS (otherwise MFSFlush would dispose the VCB)
|
|
|
|
@10 BSR MFSFlush ; flush the MFS allocation map and MDB <11Sep85>
|
|
BSR MDspsMap ; and dispose MFS map buffer <01Oct85>
|
|
BSR DsposVBlks ; finally, trash blocks for A2 volume <01Oct85>
|
|
|
|
; OK, mark it offline by zeroing the drive number field in the VCB. Then, put the
|
|
; drive number in the driver refnum field in the VCB and if it's really just Offline,
|
|
; negate that field.
|
|
|
|
ejectMark CLR.W (A1)+ ; zero drive number to mark it offline/ejected
|
|
TST.B NoEject ; Real eject call <28Oct85>
|
|
BEQ.S @1 ; br if so <28Oct85>
|
|
NEG.W D2 ; neg drive number for offline indication <29Aug85>
|
|
@1 MOVE.W D2,(A1)+ ; store drive number here for disk-switch <29Aug85>
|
|
; (negated drivenum for offline)
|
|
|
|
TST.B NoEject ; eject or offline? <29Aug85>
|
|
BEQ.S ejectIt ; go eject it if eject call <29Aug85>
|
|
|
|
; OffLine calls requeue the VCB for fairness (let some other drive get taken offline next time)
|
|
|
|
MOVE.L A2,A0 ; VCB queue element <29Aug85>
|
|
LEA VCBQHdr,A1 ; VCB queue header <29Aug85>
|
|
|
|
BSR.L DequeueTrap ; DeQueue then EnQueue to force VCB to <29Aug85><v1.4>
|
|
BSR.L EnQueueTrap ; the end for round-robin offline scheme <29Aug85><v1.4>
|
|
|
|
TST.B NoEject ; Was this a real _Offline call? <28Oct85>
|
|
BMI ejectDone ; Yes - offline br to command done <29Aug85>
|
|
|
|
; Here is where it finally gets ejected . . .
|
|
|
|
ejectIt ; shared by MFS and TFS eject code . . .
|
|
LEA Params,A0 ; general purpose I/O param block <29Aug85>
|
|
LEA IODrvNum(A0),A1 ; prepare to fill in 3-in-a-row <29Aug85>
|
|
MOVE.W D2,(A1)+ ; IODrvNum (the drive) <29Aug85>
|
|
MOVE.W D1,(A1)+ ; IORefNum (driver handling this drive) <29Aug85>
|
|
MOVE.W #EjectCode,(A1) ; CSCode (eject it!) <29Aug85>
|
|
LEA CmdDone,A1 ; completion routine just says done <29Aug85>
|
|
MOVE.L A1,IOCompletion(A0) ; <29Aug85>
|
|
_Control ,ASYNC ; asynchronous call <29Aug85>
|
|
RTS ; always return at this level <29Aug85>
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: UnMountVol
|
|
; Arguments: A0 (input) -- pointer to volume parameter block, uses IODrvNum,
|
|
; IOFileName
|
|
; D0 (output) -- error code
|
|
; This call is executed synchronously.
|
|
; Calls: FlushVolume
|
|
;
|
|
; Function: All files on the volume in the drive are closed and any changed
|
|
; directory information is written out to the diskette. Memory
|
|
; for the VCB, volume buffer, and block map is deallocated.
|
|
;
|
|
; Modification History:
|
|
; 06 Dec 82 LAK No longer ejects the diskette (This combination function
|
|
; is now done by calling Eject). If the default volume is
|
|
; unmounted, the default volume pointer is set to the first
|
|
; VCB in the VCB queue.
|
|
; 21 Dec 82 LAK Rewrote to share code with FlushVol; now calls DtrmVol to
|
|
; figure out the VCB pointer.
|
|
; 22 Apr 85 PWD Fixed to write VCBLsMod field.
|
|
; 22-Aug-85 PWD Changed to set 'volume consistent' flag in volume attributes
|
|
; before flushing MDB.
|
|
; <04Nov87> JB (C958) Rolled in UnMountVol patches PM243, PA244, PB245, and PMAB271.
|
|
; Two functional changes: 1) disallow unmount if files are
|
|
; open, and 2) allow unconditional unmount (HFS bit set)
|
|
; for the shutdown case.
|
|
; 09Jun89 BB/JB Reorder the comparison for "internal file" and "HFS vol" when
|
|
; determining whether to ignore opened FCB's. External FS's now
|
|
; can have UnMount succeed if they have "internal" files open.
|
|
; Inserted a check for MFS volumes before using file number as
|
|
; a qualifier for unmount with files open. MFS volumes will not
|
|
; allow unmount with any files open. NOTE: MultiFinder makes sure
|
|
; that the 'Desktop' file is closed before UnmountVol is called.
|
|
;_______________________________________________________________________
|
|
|
|
UnMountVolTrap:
|
|
|
|
; <SM1> FM rolled in for SuperMario, DesktopCloseDownProc closes the catalog
|
|
; and extents files. Since _Offline now no longer does this, we must make sure
|
|
; that UnMountVol always does.
|
|
|
|
bsr DesktopCloseDownProc ; <SM1> FM go take care of the desktop database <36>
|
|
|
|
bsr.s FSQueueSync ; Get in sync... <04Nov87>
|
|
clr.b FlushOnly ; Setup same as UnmountVol <04Nov87>
|
|
bsr DtrmV3 ; Call DtrmV3 to do setup stuff <04Nov87>
|
|
bne FlVolExit ; Xfer if error... <04Nov87>
|
|
|
|
moveq #0,d0 ; Initialize result code <04Nov87>
|
|
btst #HFSBit,ioTrap(a0) ; Unconditional unmount? <04Nov87>
|
|
bne FlUnMnt ; Xfer if so... <04Nov87>
|
|
;
|
|
; On return from DtrmV3, A2 contains the VCB ptr of the volume
|
|
; in question. Search the FCB array for open files that reference
|
|
; the volume...
|
|
;
|
|
movem.l a1/d1/d2,-(sp) ; Save some scratch regs <04Nov87>
|
|
move.l FCBsPtr,a1 ; FCB array base address <04Nov87>
|
|
moveq #2,d1 ; Index of 1st FCB <04Nov87>
|
|
@2
|
|
move.l fcbFlNm(a1,d1),d2 ; Is the file currently open? <04Nov87>
|
|
beq.s @4 ; Nope, try next FCB... <04Nov87>
|
|
cmp.l fcbVPtr(a1,d1),a2 ; Is the file on this volume? <04Nov87>
|
|
bne.s @4 ; No, try next FCB... <04Nov87>
|
|
cmp.w #SigWord,vcbSigWord(a2) ; Is this an MFS volume? <1.6>
|
|
beq.s @3 ; Yes, error if files are open... <1.6>
|
|
cmp.l #FSUsrCNID,d2 ; Is it an internal file? <1.6>
|
|
blo.s @4 ; Ignore it if so... <1.6>
|
|
; dead code stripped <SM1>
|
|
@3
|
|
;
|
|
; Found an open user file on the volume, so return a
|
|
; busy condition...
|
|
;
|
|
moveq #fBsyErr,d0 ; Assert UnmountVol error <04Nov87>
|
|
bra.s @5 ; Get out... <04Nov87>
|
|
@4
|
|
add.w FSFCBLen,d1 ; Next FCB array entry <04Nov87>
|
|
cmp.w (a1),d1 ; Reached the end yet? <04Nov87>
|
|
blo.s @2 ; Continue if not... <04Nov87>
|
|
@5
|
|
movem.l (sp)+,a1/d1/d2 ; Restore regs <04Nov87>
|
|
tst.w d0 ; Were files open? <04Nov87>
|
|
bne FlVolExit ; Xfer if error... <04Nov87>
|
|
bra.s FlUnMnt ; Else, go unmount... <04Nov87>
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: FlushVolume
|
|
; Arguments: A0 (input) -- VCB pointer to volume to flush
|
|
; D0 (output) -- error code
|
|
; Calls: FClose,MyWriteDB
|
|
; Called By: UnMountVol
|
|
; Function: All file buffers on the volume are flushed and any changed
|
|
; directory information is written out to the diskette.
|
|
;
|
|
; Modification History:
|
|
; 20 Nov 82 LAK Clears the modified bit after writing out the VCB.
|
|
; Removed logic to get rid of a file's own buffer after closing
|
|
; it (should be done by close routine; also changing open to
|
|
; get a pointer to a buffer from the user -> so user would
|
|
; deallocate after a close or an eject . . .
|
|
; Removed logic to deallocate the VCB buffers: this is now done
|
|
; by unmount volume . . .
|
|
; 06 Dec 82 LAK Modified for new file system data structures . . .
|
|
; 07 Dec 82 LAK Made into an external procedure.
|
|
; 21 Dec 82 LAK Changed to flush file buffers but not close the files; now
|
|
; combines code of both unmountvol and flushvol.
|
|
; 13 Jan 83 LAK Zeros rest of last block map block before writing it out;
|
|
; some cosmetic and minor changes. Fills in IODrvNum field.
|
|
; 26 Jan 83 LAK Doesn't read in the master block first anymore; always
|
|
; flushes dirty volume buffer.
|
|
; 02 Jun 83 LAK Made flush of off-line volume a no-op; also allows unmount
|
|
; of an off-line volume.
|
|
; 11 Mar 85 PWD Changed to call BTClose for files with non-nil FCBBTCBPtrs as
|
|
; a temporary patch (eventually this will be part of FlClose).
|
|
; 4 Apr 85 PWD B*-Tree are now handled by FClose; removed calls to BTClose.
|
|
; 1 May 85 PWD Added code to free WDCBs pointing to unmounted volume
|
|
; on UnMount
|
|
; 4-Jun-85 PWD Changed to write MDB as last block (should always have highest
|
|
; sequence number in tags).
|
|
; <29Aug85> LAK MDB cannot be written after control files are closed.
|
|
;_______________________________________________________________________
|
|
|
|
FlushVFiles:
|
|
MOVE.L (SP)+,-(A6) ; Save return address for ,ASYNC calls <30Aug85>
|
|
MOVEM.L A0-A5/D1-D7,-(A6) ; Save all regs except D0 <11Sep85>
|
|
|
|
; scan through the FCBs and flush any files on this volume that are open
|
|
; (also close them if we are unmounting the volume . . .)
|
|
|
|
BSR Gt1stFCB
|
|
ckNxtFCB TST.L FCBFlNm(A1,D1) ; file open?
|
|
BEQ.S ckNxtF1 ; br if not
|
|
|
|
CMP.L FCBVPtr(A1,D1),A2 ; pointing at this VCB?
|
|
BNE.S ckNxtF1 ; nope.
|
|
BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
|
|
BNE.S @1 ; Nope - all's safe <28Aug85>
|
|
CMP.L #FSUsrCNID,FCBFlNm(A1,D1) ; Check file id - internal file?
|
|
BCS.S ckNxtF1 ; If LO, yes - wait until later <28Aug85>
|
|
@1 BSR FClose ; file is on this volume so flush it
|
|
BNE.S fvFilesExit ; report any errors
|
|
|
|
ckNxtF1 BSR GtNxtFCB ; look at next file
|
|
BCS.S ckNxtFCB ; until we have looked at them all
|
|
MOVEQ #0,D0 ; we're cool
|
|
|
|
fvFilesExit
|
|
MOVEM.L (A6)+,A0-A5/D1-D7 ; Restore regs <11Sep85>
|
|
MOVE.L (A6)+,-(SP) ; restore return address
|
|
TST.W D0
|
|
RTS
|
|
|
|
FlushVolTrap:
|
|
BSR FSQueue ; wait our turn
|
|
ST FlushOnly ; only flushing . . .
|
|
|
|
; first, find the appropriate VCB in our queue
|
|
|
|
BSR.S DtrmV3 ; check name, drive number, etc.
|
|
BNE.S FlVolExit ; exit if no such volume
|
|
FlUnMnt: ; <04Nov87>
|
|
BSR.S CkExtFS ; see if it's for an external fs
|
|
BNE.S FlVolExit ; exit if so
|
|
|
|
BSR.S FlushVFiles ; flush all files on this volume
|
|
BNE.S FlVolExit
|
|
|
|
; All files on this volume are flushed now. Update the volume information as
|
|
; appropriate, depending on the file structure:
|
|
|
|
BSR TFSVCBTst ; is this a TFS volume? <01Oct85>
|
|
BEQ.S @1 ; br if so <11Sep85>
|
|
BSR MFSFlush ; flush the MFS allocation map and MDB <11Sep85>
|
|
BRA.S FlVolExit ; and exit . . . <11Sep85>
|
|
|
|
; Unmounting a TFS volume: close the volume control B*-Tree and use the
|
|
; volume buffer to write out the MDB
|
|
;
|
|
; From UnmountForTheNineties in FileMgrPatches.a
|
|
; Here's the change: we no longer check whether the volume is offline. Instead we always
|
|
; go ahead and close the control files, since we no longer close them on _Offline or _Eject.
|
|
;
|
|
@1: tst.w vcbDrvNum(a2) ; Check drive number: vol. offline?
|
|
beq.s CloseControlFiles ; If zero, it is; control files are open & flushed
|
|
|
|
BSR FlushBuffers ; share routine with Eject to do it all <01Oct85>
|
|
BNE.S FlIOErrExit ; Punt on errors
|
|
|
|
BRA.S FlVolDone ;
|
|
|
|
; here begins CloseControlFiles, which is derived from FlushBuffers
|
|
; Now we have to close the control files because we no longer close them
|
|
; in Eject and Offline
|
|
|
|
CloseControlFiles
|
|
tst.b FlushOnly ; only do this if we are in fact unmounting the volume <SM5> CSS
|
|
bne.s FLVolOK ; just a flush <SM5> CSS
|
|
|
|
movea.l FCBsPtr,A1 ; Point to FCB array
|
|
|
|
move.w vcbCTRef(a2),d1 ; Catalog B*-Tree file refnum
|
|
jsr FClose ; Close the file itself
|
|
bne.s FlVolExit ; Punt on errors
|
|
|
|
move.w vcbXTRef(a2),d1 ; Extent B*-Tree file refnum
|
|
jsr FClose ; Close the file itself
|
|
bne.s FlVolExit ; Rats - and we were SO CLOSE.. •• is this what we want?
|
|
|
|
jsr DsposVBlks ; Trash blocks for a2 volume
|
|
|
|
FlVolDone TST.B FlushOnly ; only flushing?
|
|
BNE.S FlVolOK ; br if so
|
|
|
|
; For UnMountVol, dequeue the VCB and trash any WDCBs for this volume . . .
|
|
|
|
BSR DsposVCB ; share code with MountVol error routine <30Aug85>
|
|
|
|
FlVolOK MOVEQ #0,D0 ; no error
|
|
FlIOErrExit ;
|
|
FlVolExit BRA CmdDone
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CkExtFS
|
|
; Arguments: A2.L (input) -- VCB pointer
|
|
; D0.W (output) -- 0=belongs to us, ExtFSErr=belongs to another
|
|
; Called By:
|
|
; Function: Simple routine to separate out calls to be handled by an
|
|
; external file system.
|
|
;
|
|
; Modification History:
|
|
; 06 Dec 82 LAK New today.
|
|
;_______________________________________________________________________
|
|
|
|
CkExtFS:
|
|
MOVE.L jCkExtFS,-(SP) ; jump table entry for vCkExtFS <27Oct86>
|
|
RTS ; go there <27Oct86>
|
|
vCkExtFS ; 'vectored' CkExtFS routine <27Oct86>
|
|
|
|
MOVE.W VCBFSID(A2),D0 ; is this VCB for us?
|
|
BEQ.S @1 ; br if so
|
|
MOVEQ #ExtFSErr,D0
|
|
@1 RTS
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: DtrmVol,DtrmV1,DtrmV2,DtrmV3
|
|
; Arguments: HFSFlags (input) -- who really sets this up??? <29Aug85>
|
|
; A0.L (input) -- IOFileName(A0) = ptr to path name
|
|
; D0.W (output) -- 0 or error code: NSVErr
|
|
; D2.W (output) -- pathname length (not including any vol prefix)
|
|
; D3.W (output) -- 0 if no vol name specified, non-zero otherwise
|
|
; A2.L (output) -- VCB pointer
|
|
; A3.L (output) -- WDCB pointer or zero (if none specified)
|
|
; A4.L (output) -- pathname ptr (not including any vol prefix)
|
|
; All other regs are preserved
|
|
; Makes use of the fact that all IO parameter blocks have
|
|
; their filename pointers and drive numbers in the same spot.
|
|
; Calls: _CmpString,QWordSearch,GetVCBDrv,GetVCBRfn
|
|
; Called By: SetVol,UnMountVol,FlushVol,Open,Create,Delete,Rename,
|
|
; GetFileInfo(DtrmV1),GetVolInfo(DtrmV1,DtrmV3)
|
|
; Function: Determine what volume is being used in a name. Main entry
|
|
; requires a name pointer; DtrmV2 also does, but the pointer is
|
|
; passed in D2. DtrmV1 just looks at drive number; DtrmV3
|
|
; looks at name field if not nil, otherwise drive number.
|
|
;
|
|
; Modification History:
|
|
; 02 Dec 82 LAK Changed to set CCR when done. Changed to reflect that volumes
|
|
; off-line have a zero VCB pointer. Preserves non-interface
|
|
; regs. Searches thru VCB queue as mountVol, unmountVol do.
|
|
; 10 Dec 82 LAK Changed to look at drive number field when there is no
|
|
; volume prefix. Now uses global string compare proc.
|
|
; 13 Dec 82 LAK Added entry point DtrmVol1 for GetFileInfo.
|
|
; 13 Jan 83 LAK Calls OS _CmpString proc. Don't ignore parity bit when looking
|
|
; for colon in name.
|
|
; 23 Jan 83 LAK Changed DtrmV2 entrypoint to have pointer already; report
|
|
; error at DtrmVol and DtrmV2 entrys if name ptr is nil;
|
|
; deleted DtrmV1 (just call GetDrvVCB).
|
|
; 25 May 83 LAK A4 points to first filename byte now.
|
|
; 02 Jun 83 LAK Changed to support VRefNum: GetDrvVCB has been factored
|
|
; out and made into GetVCBDrv, GetVCBRfn
|
|
; 23 Feb 85 GJC added TFS support for pathnames of the form
|
|
; volname:<dirname:><dirname:><etc>filename (scan filename from
|
|
; left to right).
|
|
; also, added support for working directory queue and
|
|
; WDRefnums (search WDCB queue for VRefNums < WDRfnMax).
|
|
; 28-Feb-85 PWD Changed to stash WDCB pointers in A3, always return VCB pointer
|
|
; in A2. Note that A3 is CLEARED in cases where no WDCB is
|
|
; specified, INCLUDING MFS CALLS.
|
|
; 1-Mar-85 PWD Changed to check for and ignore zero-length volume names
|
|
; (possible if WDCB/partial pathname is specified). Name pointer
|
|
; is left pointing AFTER leading colon at first pathname element.
|
|
; 22-Aug-85 PWD Changed to skip search path if requested through lo-mem flag
|
|
; (for GetFileInfo/GetCatInfo by index).
|
|
; <29Aug85> LAK Rewrote in a more straightforward fashion. Only error returned
|
|
; now is NSVErr.
|
|
; <06Sep85> LAK Slight modification to DtrmV3 prefix to prevent passing to DtrmVol
|
|
; if IOFileName points to a zero-length string (for the dubious
|
|
; result of making CatMove work with a zero-length string . . .).
|
|
; <25Sep85> PWD Added support for PMSPHook and PMSP Enable/Disable.
|
|
;
|
|
; Test: no vol name, very short vol names, vol name which is only a colon,
|
|
; internal-external-no volume,only drive specified
|
|
;
|
|
; NOTE: WHY ZERO THE ENTIRE PMSP BLOCK?
|
|
;_______________________________________________________________________
|
|
|
|
DtrmV3:
|
|
MOVE.L jDtrmV3,-(SP) ; jump table entry for vDtrmV3 <27Oct86>
|
|
RTS ; go there <27Oct86>
|
|
vDtrmV3 ; 'vectored' DtrmV3 routine <27Oct86>
|
|
|
|
MOVE.L IOFileName(A0),D2 ; entry for flush,set,eject,unmountvol <06Sep85>
|
|
MOVE.L D2,A4 ; <06Sep85>
|
|
BEQ.S DtrmV1 ; br if nil filename pointer (D2,A4=0) <06Sep85>
|
|
TST.B (A4) ; is it a zero-length name? <06Sep85>
|
|
BNE DtrmVol ; if non-zero, check for vol prefix <06Sep85>
|
|
|
|
MOVEQ #0, d2 ; make sure string length is set to zero <SM1>
|
|
; (this is from FixDtrmV3 in FileMgrPatches.a)
|
|
DtrmV1:
|
|
MOVE.L jDtrmV1,-(SP) ; jumptable entry for vDtrmV1 <29Oct85>
|
|
RTS ; go there <29Oct85>
|
|
vDtrmV1 ; 'vectored' DtrmV1 routine <29Oct85>
|
|
|
|
MOVEQ #0,D3 ; No volume name specified <29Aug85>
|
|
SUB.L A3,A3 ; Assume no WDCB spec'd for now... <29Aug85>
|
|
|
|
MOVE.W IOVRefNum(A0),D0 ; volume refnum
|
|
BEQ.S dtrmDeflt ; br if no drive/vrefnum specified <29Aug85>
|
|
BMI.S dtrmVRef ; br if volume refnum <29Aug85>
|
|
BSR GetVCBDrv ; try to figure VCB by drive number <29Aug85>
|
|
BRA.S dtrmGotCk ; <29Aug85>
|
|
|
|
dtrmVRef CMP.W #WDRfnMax,D0 ; Check against max. WDRefNum <29Aug85>
|
|
BLE.S @1 ; If LE, it's a working directory RefNum <29Aug85>
|
|
BSR GetVCBRfn ; try to figure VCB by volume refnum <29Aug85>
|
|
BRA.S dtrmGotCk ; <29Aug85>
|
|
|
|
@1 BSR GetWDCBRfn ; search WDCB queue for WD entry <29Aug85>
|
|
|
|
dtrmGotCk BEQ.S dtrmGotVol ; br if A2->VCB <29Aug85>
|
|
dtrmErrRTS MOVEQ #NSVErr,D0 ; let's be consistent nowadays . . . <29Aug85>
|
|
RTS
|
|
|
|
dtrmDeflt MOVE.L DefVCBPtr,D0 ; Is a default set up? <29Aug85>
|
|
BEQ.S dtrmErrRTS ; br if no name, no drive, no refnum, no default
|
|
MOVEA.L D0,A2 ; Otherwise, set it up for use
|
|
MOVEA.L WDCBsPtr,A3 ; Point to the WDCB array
|
|
ADDQ.L #2,A3 ; Point to the default WDCB there
|
|
|
|
; OK, we have A2 set up with the VCB pointer, and A3 -> WDCB if specified by WDCB or default
|
|
|
|
dtrmGotVol MOVEQ #0,D0 ; All's well so far
|
|
MOVE.L A2,ReqstVol ; save in case of offline, ext fs vols
|
|
|
|
; Now that we've determined a volume to work with, check to make sure some
|
|
; defaults are set up to deal with the possibility that the file we're looking
|
|
; for doesn't appear in the first directory tried (if none was specified
|
|
; explicitly):
|
|
|
|
BTST #NoPMSP,HFSFlags ; PMSP disabled? <25Sep85>
|
|
BNE.S @0 ; If set, don't search any other directories <25Sep85>
|
|
|
|
BTST #SkipPMSP,HFSFlags ; Don't bother with PMSP for this operation? <22Aug85>
|
|
BEQ.S dtrmPath ; If flag isn't set, give it a chance <22Aug85>
|
|
|
|
; Zero the search path:
|
|
|
|
@0 MOVE.L A4,-(SP) ; Create scratch registers <22Aug85>
|
|
MOVEA.L PMSPPtr,A4 ; Point to the search path <22Aug85>
|
|
ADDQ.L #2,A4 ; Point to first entry <22Aug85>
|
|
MOVEQ #((PMSPSize-SPHdrSize-2)/2)-1,D0 ; Pick up length of PMSP <22Aug85>
|
|
@1 CLR.W (A4)+ ; Clear out the search path <22Aug85>
|
|
DBRA D0,@1 ; <22Aug85>
|
|
MOVE.L (SP)+,A4 ; Restore the original A4 <22Aug85>
|
|
|
|
dtrmExOK MOVEQ #0,D0 ; All's well so far <29Aug85>
|
|
RTS ; So quit while we're ahead. <29Aug85>
|
|
|
|
dtrmPath BTST #HFSBit,ioTrap(A0) ; Use of HFSBit (9) mod 8 is OK on high byte
|
|
BEQ.S @1 ; If no TFS trap, there's no DirID
|
|
TST.L ioDirID(A0) ; Otherwise, was one specified?
|
|
BNE.S dtrmExOK ; Yes - there'll be no defaulting.
|
|
|
|
@1 MOVEM.L A4/A1/D2/D4,-(SP) ; Save scratch registers from all this wickedness
|
|
; for use as PMSP pointers...
|
|
MOVEA.L PMSPPtr,A4 ; Point off to the Poor Man's Search Path
|
|
MOVE.W PMSPIndx(A4),D4 ; Pick up the default volume index
|
|
BGT.S dtrmPthUse ; If it's initialized, go for it
|
|
|
|
; Initialize the search path list:
|
|
|
|
MOVEQ #2,D4 ; Index beyond the size word to set up 1st entry
|
|
MOVE.W VCBVRefNum(A2),D2 ; Pick up the volume's VRefNum for use
|
|
|
|
; The first entry is the default volume/directory:
|
|
|
|
MOVE.L A3,D0 ; Was a WDCB [or default] specified?
|
|
BEQ.S @2 ; Nope - use the root
|
|
MOVE.L WDDirID(A3),D0 ; Otherwise, we want the default DirID
|
|
BRA.S @3 ; [A3 points to a WDCB]
|
|
@2 MOVEQ #FSRtDirID,D0 ; No WDCB - use the root
|
|
@3 BSR.S AddSPEntry ; Add this entry to the search path
|
|
|
|
; The remainder only makes sense for TFS volumes, which actually have
|
|
; distinguishable directories:
|
|
|
|
BSR TFSVCBTst ; is this a TFS volume? <01Oct85>
|
|
BNE.S dtrmPthEnd ; Nope - put an end to it all
|
|
|
|
; The second entry is the directory referred to by BootDrive, if it's
|
|
; a working directory on the same volume:
|
|
|
|
dtrmPth2 MOVE.W BootDrive,D0 ; Pick up BootDrive
|
|
BGE.S dtrmPth3 ; If it's a real DriveNum, forget it
|
|
; (it would just refer to the root, anyways)
|
|
CMP.W #WDRfnMax,D0 ; Is it a working directory?
|
|
BGT.S dtrmPth3 ; If not, forget it
|
|
BSR GetWDCBRfn ; Look up the VCB (sets A2 and A3)
|
|
BNE.S dtrmPth3 ; Punt on errors
|
|
CMP.W VCBVRefNum(A2),D2 ; Same volume?
|
|
BNE.S dtrmPth3 ; If not, forget it
|
|
MOVE.L WDDirID(A3),D0 ; Pick up the DirID from the WDCB
|
|
BSR.S AddSPEntry ; And add the entry to the PMSP
|
|
|
|
; The third entry is the system directory on the same volume:
|
|
|
|
dtrmPth3 MOVEA.L ReqstVol,A2 ; Revert back to the requested volume
|
|
MOVE.L VCBFndrInfo(A2),D0 ; Pick up the system DirID
|
|
BEQ.S dtrmPthEnd ; If it doesn't exist, just skip it.
|
|
BSR.S AddSPEntry ; Add this to the search path, too
|
|
|
|
; The fourth entry is the root of the volume: <25Sep85>
|
|
|
|
*EX-CODE:* MOVEQ #FSRtDirID,D0 ; Pick up the root directory ID <25Sep85>
|
|
*EX-CODE:* BSR.S AddSPEntry ; And add it to the search path <25Sep85>
|
|
|
|
; *Add directories on the boot drive, too? (a setup FROUGHT with peril!)*
|
|
|
|
dtrmPthEnd CLR.W SPVRefNum(A4,D4) ; Zero last VRefNum to indicate end of PMSP.
|
|
MOVEQ #2,D4 ; Set up to point to first entry in PMSP
|
|
MOVE.W D4,PMSPIndx(A4) ; Store it for future reference
|
|
|
|
; Check if a PMSP hook was defined, and give it a chance to change the PMSP table <30Sep85>
|
|
; (pointed to by A4), and/or the PMSP index (D4) using the VCB (A2) and IOPB (A0) <30Sep85>
|
|
|
|
MOVE.L PMSPHook(A4),D0 ; Pick up the hook, if any <30Sep85>
|
|
BEQ.S dtrmPthUse ; If zero, no hook is currently installed <30Sep85>
|
|
MOVEA.L D0,A1 ; Shift hook address over for dispatch <30Sep85>
|
|
JSR (A1) ; Call the PMSP hook <30Sep85>
|
|
|
|
dtrmPthUse MOVE.W SPVRefNum(A4,D4),D0 ; Pick up the default VRefNum
|
|
BSR GetVCBRfn ; Find the corresponding VCB
|
|
BNE.S @1 ; Br if found no more
|
|
|
|
MOVEA.L WDCBsPtr,A3 ; Point to WDCB table
|
|
ADDA.W #(2+WDCBLen),A3 ; Point A3 off to newly created default
|
|
MOVE.L A2,WDVCBPtr(A3) ; Set up second WDCB VCB pointer
|
|
MOVE.L SPDirID(A4,D4),WDDirID(A3) ; Set up second WDCB DirID
|
|
CLR.L WDCatHint(A3) ; No catalog hint
|
|
CLR.L WDProcID(A3) ; No ProcID
|
|
|
|
MOVEQ #0,D0 ; We're all set, and all is well.
|
|
|
|
@1 MOVEM.L (SP)+,A4/A1/D2/D4 ; Restore scratch registers to original state <25Sep85>
|
|
RTS
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Add an entry to the Poor Man's Search path
|
|
;
|
|
; Input: D0 = DirID
|
|
; D2 = VRefNum
|
|
; D4 = PMSP index of next free entry
|
|
; A4 = PMSP table pointer
|
|
;
|
|
; Output: D4 = updated to point to next entry if entry is used.
|
|
;
|
|
; D0 is clobbered.
|
|
;_______________________________________________________________________
|
|
|
|
AddSPEntry:
|
|
|
|
; Look for an existing entry in the PMSP with the same VRefNum/DirID combination:
|
|
|
|
MOVE.L D4,-(SP) ; Save PMSP index across search
|
|
MOVEQ #2,D4 ; Index D4 to first entry in PMSP
|
|
@10 CMP.L (SP),D4 ; Reached the free slot already?
|
|
BCC.S @60 ; Yes - fill in the entry
|
|
CMP.W SPVRefNum(A4,D4),D2 ; Match on VRefNum?
|
|
BNE.S @40 ; If not, give up
|
|
CMP.L SPDirID(A4,D4),D0 ; Match on DirID?
|
|
BEQ.S @50 ; Yes - No need to fill this one in again
|
|
@40 ADDQ.W #SPEntLen,D4 ; Point to the next entry
|
|
CMP.W (A4),D4 ; Exceeded the table size?
|
|
BLO.S @10 ; Nope - continue
|
|
|
|
@50 MOVEQ #0,D0 ; Yes - no more room
|
|
@60 MOVE.L (SP)+,D4 ; Restore D4 to index to free entry again
|
|
|
|
; Now consider adding the new entry:
|
|
|
|
TST.L D0 ; Check the DirID: still want to use it?
|
|
BEQ.S @90 ; If it's zeroed, there's no point
|
|
MOVE.W D2,SPVRefNum(A4,D4) ; Otherwise, set up the VRefNum
|
|
MOVE.L D0,SPDirID(A4,D4) ; And the new DirID
|
|
ADDQ.W #SPEntLen,D4 ; Advance to the next entry
|
|
|
|
@90 RTS
|
|
|
|
DtrmVol: MOVE.L IOFileName(A0),D2 ; get pointer to 'volume:<dirname:>filename'
|
|
|
|
DtrmV2:
|
|
MOVE.L jDtrmV2,-(SP) ; jump table entry for vDtrmV2 <19Feb87>
|
|
RTS ; go there <19Feb87>
|
|
vDtrmV2 ; 'vectored' DtrmV2 routine <19Feb87>
|
|
MOVEM.L D4-D6/A0-A1,-(SP) ; save regs
|
|
TST.L D2 ; Name specified?
|
|
BEQ.S NoNameErr ; need a name this entrypoint
|
|
MOVE.L D2,A4
|
|
MOVEQ #0,D2 ; clear index into name (long for later add)
|
|
MOVEA.L D2,A3 ; Clear WDCB pointer (never specified)
|
|
MOVE.B (A4)+,D2 ; len of file name
|
|
BEQ.S NoNameErr ; no zero-length names
|
|
MOVEQ #0,D3 ; initialize loop count to zero
|
|
|
|
@1 MOVE.B 0(A4,D3),D4 ; watch for colons in the name
|
|
CMP.B #$3A,D4 ; ':'?
|
|
BEQ.S @2 ; found possible volume name
|
|
ADDQ.W #1,D3 ; scan entire name from front to back
|
|
CMP.W D3,D2 ; have we scanned the entire length yet?
|
|
BNE.S @1 ; If more to scan, go for it
|
|
BRA.S @3 ; Otherwise, go look by DrvNum/VRefNum
|
|
|
|
@2 SUB.L D3,D2 ; file name len excluding volume part
|
|
SUBQ.W #1,D2 ; and the colon
|
|
MOVE.L A4,A1 ; ptr to 1st char of vol name string
|
|
ADD.L D3,A4 ; ptr to first colon in pathname string
|
|
ADDA.L #1,A4 ; now pointing to the pathname
|
|
|
|
TST.W D3 ; Have we scanned over any characters?
|
|
BGT.S VolSpcfd ; Yes - go look for volume by name
|
|
@3 BSR DtrmV1 ; no volume prefix; use DrvNum/VRefNum
|
|
|
|
DtrmDone MOVEM.L (SP)+,D4-D6/A0-A1 ; restore regs
|
|
TST.W D0 ; set condition codes
|
|
RTS
|
|
|
|
NoNameErr MOVEQ #BdNamErr,D0 ; zero name pointer
|
|
BRA.S DtrmDone
|
|
|
|
; A volume name was specified. figure out which one (if any)
|
|
|
|
VolSpcfd MOVE.L VCBQHdr+QHead,D0 ; search the VCB queue
|
|
CkVol: BEQ.S @2 ; br if end of queue reached
|
|
MOVE.L D0,A2 ; next VCB pointer
|
|
LEA VCBVN(A2),A0 ; string pointer
|
|
MOVEQ #0,D0
|
|
MOVE.B (A0)+,D0 ; length of (A0) string
|
|
SWAP D0
|
|
MOVE.W D3,D0 ; length of (A1) string
|
|
_CmpString ; compare strings @A0, @A1
|
|
BNE.S @1 ; br if not equal
|
|
MOVE.L A2,ReqstVol ; note the requested volume
|
|
BRA.S DtrmDone ; br if it compares
|
|
|
|
@1 MOVE.L QLink(A2),D0
|
|
BNE.S CkVol
|
|
|
|
@2 MOVEQ #NSVErr,D0 ; no volume name match, so volname must
|
|
BRA.S DtrmDone ; be dir name, so use drvnum/vrefnum
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: SetPMSP
|
|
; Arguments: A0.L (input) -- I/O volume parameter block: uses ioCompletion
|
|
; and ioMisc ($1C).
|
|
; D0.W (output) -- error code
|
|
; Calls: FSQueue,CmdDone
|
|
;
|
|
; Function: Specify the behavior of TFS' Poor Man's Search Path.
|
|
;
|
|
; ioCompletion(A0) is the address of a hook procedure (zero to disable)
|
|
; which is called when TFS has just initialized the PMSP table.
|
|
; The hook is called with (A4,D4) pointing to the first PMSP entry.
|
|
;
|
|
; ioMisc(A0) is a word, the LSB of which determines whether the PMSP is
|
|
; used at all (if set) or ignored alltogether (if clear).
|
|
;
|
|
; Modification History:
|
|
; <25Sep85> PWD New today.
|
|
;_______________________________________________________________________
|
|
|
|
SetPMSP: BSR FSQueue ; Patiently wait our turn
|
|
|
|
MOVE.L ioPMSPHook(A0),D0 ; Pick up the hook procedure
|
|
BMI.S @1 ; If negative, don't install it
|
|
MOVEA.L PMSPPtr,A1 ; Point to the PMSP table
|
|
MOVE.L D0,PMSPHook(A1) ; Install the new hook
|
|
|
|
@1 MOVE.W ioPMSPFlg(A0),D0 ; Pick up the accompanying boolean
|
|
BCLR #NoPMSP,HFSFlags ; Clear flag, enabling PMSP
|
|
BTST #0,D0 ; Test the LDB [a la Pascal]
|
|
BNE.S SetPMSPOK ; If enabled, we're set
|
|
BSET #NoPMSP,HFSFlags ; If flag is clear, PMSP is off
|
|
|
|
SetPMSPOK MOVEQ #0,D0 ; Always a big hit
|
|
BRA CmdDone ; So let's just call it a day here
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: GetVolInfo
|
|
; Arguments: A0.L (input) -- I/O volume parameter block: uses all volume
|
|
; fields.
|
|
; D0.W (output) -- error code
|
|
; Calls: FSQueue,CmdDone
|
|
;
|
|
; Function: Return information about the volume in a mounted drive.
|
|
; If the IOVolIndex field is 0,
|
|
; the name of the default volume is returned; if non-zero, the
|
|
; name of the nth mounted volume is returned. The maximum length
|
|
; of a volume name is 27 bytes. The drive number for the volume
|
|
; is also returned.
|
|
;
|
|
; Modification History:
|
|
; 07 Dec 82 LAK Changed to support new file system data structures.
|
|
; 16 Dec 82 LAK Removed backup file lgth subtract in free blk determination.
|
|
; 21 Dec 82 LAK Changed to call DtrmVol to figure the volume name. Free
|
|
; blocks comes from VCB info already stored.
|
|
; 14 Jan 83 LAK The latest changes.
|
|
; 23 Jan 83 LAK Changed to use the volindex field, call XferVName.
|
|
; 03 Jun 83 LAK Added in-use bit: true if any files on the volume are open;
|
|
; returns volume refnum now instead of drive number.
|
|
; 6-Aug-85 PWD Changed to call external file system for non-Macintosh volumes
|
|
; AFTER filling in the I/O parameter block information.
|
|
; 15-Aug-85 PWD Changed to add ioVFilCnt and ioVDirCnt fields
|
|
; 21-Sep-85 PWD Changed to exclude B*-Tree file allocations from NmAlBlks
|
|
; 21-Sep-85 PWD Changed to return directory valence instead of VCBNmFls if
|
|
; ioVRefNum is a working directory refNum.
|
|
; 24-Sep-85 PWD Fixed bug (MOVE.L vs. MOVEM.L) in directory valence lookup
|
|
; 11-Oct-85 PWD Changed to pin NmAlBlks and NmFrBlks at (32767*1000)/1024
|
|
; instead of 32767 for programs that figure in 'decimal K'
|
|
; 13-Oct-85 PWD Fixed bug: don't try to read working directory valence for
|
|
; external FS volumes.
|
|
; 27-Oct-85 PWD Changed to ignore volume control files in determining vol. busy
|
|
; Changed to set bit 5 in attributes if volume is default
|
|
;
|
|
; - if this was the twin of GetFileInfo, the volume really shouldn't have to
|
|
; be mounted . . . if it is, get the info from the VCB and block map: if
|
|
; not, read the drive's master block into a stack buffer (would have to
|
|
; read the block map, tho, to determine the number of free blocks) . . .
|
|
;_______________________________________________________________________
|
|
|
|
GetVolInfo:
|
|
BSR FSQueue ; queue up the request
|
|
|
|
MOVE.W IOVolIndex(A0),D2 ; if positive,
|
|
BGT.S @3 ; go search by index
|
|
BEQ.S @1 ; if zero, go by drive number/default
|
|
|
|
BSR DtrmV3 ; if negative, go by name
|
|
BRA.S @2
|
|
|
|
@1 BSR DtrmV1 ; figure by drvnum, vrefnum, or default
|
|
@2 BNE TGVIDone
|
|
BRA.S RetVolInfo
|
|
|
|
@3 MOVEQ #0,D3 ; Never any name specified <25Sep85>
|
|
; (ioFileName is output arg) <25Sep85>
|
|
CLR.W ioVRefNum(A0) ; make sure this gets filled in later <25Sep85>
|
|
MOVE.L VCBQHdr+QHead,D1 ; we want nth VCB in queue
|
|
@4 BEQ NSVErrXit ; exit with err at end of queue
|
|
SUBQ.W #1,D2 ; the one we want?
|
|
MOVE.L D1,A2
|
|
BEQ.S RetVolInfo ; br if so
|
|
MOVE.L QLink(A2),D1 ; if not, keep traversing the queue
|
|
BRA.S @4
|
|
|
|
; first copy the heart of the VCB into the parameter block
|
|
|
|
RetVolInfo MOVEQ #IOVDirLen-2,D0 ; number of bytes to straight copy
|
|
@4 MOVE.W VCBCrDate(A2,D0.W),IOVCrDate(A0,D0.W)
|
|
SUBQ #2,D0
|
|
BPL.S @4
|
|
|
|
BSET #6,ioVAtrb+1(A0) ; set if any files are opened <28Oct85>
|
|
BSR Gt1stFCB ; get (A1,D1) pointing to first FCB
|
|
|
|
@0 CMP.L FCBVPtr(A1,D1),A2 ; file open on this volume?
|
|
BNE.S @1 ; br if so
|
|
BSR TFSVCBTst ; Are we looking at a TFS VCB? <27Oct85>
|
|
BNE.S @2 ; Nope - all files are fair game <27Oct85>
|
|
MOVE.L FCBFlNm(A1,D1),D0 ; Check the file number <27Oct85>
|
|
CMP.L #FSUsrCNID,D0 ; Is it a system control file? <27Oct85>
|
|
BHS.S @2 ; Accept only the highest quality... <27Oct85>
|
|
|
|
@1 BSR GtNxtFCB ; get next one until we run out
|
|
BCS.S @0
|
|
BCLR #6,ioVAtrb+1(A0) ; 0 if no open files match <28Oct85>
|
|
|
|
@2 BCLR #5,ioVAtrb+1(A0) ; Assume this volume is not the default.<27Oct85>
|
|
CMPA.L DefVCBPtr,A2 ; Check the default volume pointer <27Oct85>
|
|
BNE.S @3 ; If this isn't it . . . <27Oct85>
|
|
BSET #5,ioVAtrb+1(A0) ; If this is default, drop a hint. <27Oct85>
|
|
|
|
@3 SUBA.L A3,A3 ; Clear WDCB pointer <14Oct85>
|
|
|
|
TST.W ioVolIndex(A0) ; Check volIndex: <21Sep85>
|
|
BGT.S retVRef ; If vol was indexed, leave things be <21Sep85>
|
|
TST.W D3 ; Was a volume name specified? <21Sep85>
|
|
BNE.S retVRef ; If so, always return real file count <21Sep85>
|
|
MOVE.W ioVRefNum(A0),D1 ; Check VRefNum supplied: <21Sep85>
|
|
BGT.S retVRef ; If driveNum, ignore it <21Sep85>
|
|
BLT.S @5 ; If negative, might be a WDRefNum <21Sep85>
|
|
MOVEQ #2,D1 ; If 0, look at default WDCB <21Sep85>
|
|
BRA.S @7 ; <21Sep85>
|
|
|
|
@5 CMP.W #WDRfnMax,D1 ; Otherwise, compare to max WDRefNum <21Sep85>
|
|
BGT.S retVRef ; If it's a real VRefNum, we're OK <21Sep85>
|
|
|
|
; a WDRefNum was supplied as VRefNum: change the number of files to be the <21Sep85>
|
|
; valence of the directory in question: <21Sep85>
|
|
|
|
SUB.W #WDRfnMin,D1 ; Change WDRefNum to index <21Sep85>
|
|
@7 MOVE.L WDCBsPtr,A3 ; Point to WDCB array <12Oct85>
|
|
ADD.W D1,A3 ; Point A3 to WDCB for ext. FS <13Oct85>
|
|
BSR ExtOffLinCk ; Is this an external file system vol? <13Oct85>
|
|
BNE.S retVRef ; Yes - don't try to read the catalog <13Oct85>
|
|
|
|
MOVEM.L A0-A1,-(A6) ; Use A0,A1 as scratch registers <21Sep85>
|
|
MOVEA.L WDCBsPtr,A1 ; Point to WDCB array <21Sep85>
|
|
MOVE.L WDDirID(A1,D1),D0 ; Pick up the DirID in question <21Sep85>
|
|
CMP.L #FSRtDirID,D0 ; Is it the root directory anyway? <21Sep85>
|
|
BEQ.S @8 ; If so, don't make special efforts <21Sep85>
|
|
|
|
MOVE.L WDCatHint(A1,D1),D2 ; Pick up directory hint <21Sep85>
|
|
SUBA.L A0,A0 ; CName = Nil <21Sep85>
|
|
JSR CMGetCN ; Look up the directory <21Sep85>
|
|
BNE.S @8 ; If can't find it, forget it. <21Sep85>
|
|
|
|
MOVE.W dirVal(A1),D0 ; Store directory valence <21Sep85>
|
|
MOVEM.L (A6)+,A0-A1 ; Restore scratch regs <21Sep85>
|
|
MOVE.W D0,ioVNmFls(A0) ; Replace file count w. dir. valence <21Sep85>
|
|
BRA.S retVRef ; And continue <21Sep85>
|
|
|
|
@8 MOVEM.L (A6)+,A0-A1 ; Continue without changing file count <24Sep85>
|
|
|
|
; Do some hairy checking: if a working directory was specified, it shouldn't
|
|
; be overwritten by the volRefNum. However, if a volume NAME was used, the
|
|
; volRefNum field is ignored, and SHOULD be filled in with the volume's VRefNum.
|
|
|
|
retVRef TST.W D3 ; Was a volume name specified?
|
|
BNE.S @10 ; If so, always return volRefNum
|
|
TST.W IOVRefNum(A0) ; VRefNum or WDRefNum supplied?
|
|
BLT.S @20 ; If so, leave it alone
|
|
@10 MOVE.W VCBVRefNum(A2),IOVRefNum(A0) ; return volume refnum
|
|
@20 BSR XferVName ; copy volume name
|
|
|
|
retAlBks BSR TFSVCBTst ; Are we dealing with a TFS volume? <13Oct85>
|
|
BNE.S @25 ; If not, don't fiddle with NmAlBlks<21Sep85>
|
|
|
|
; Subtract the physical sizes of the extent B*-Tree and the catalog B*-Tree <21Sep85>
|
|
; from the volume size, so that the difference between the volume size and <21Sep85>
|
|
; the free space reflects only the user's allocations: <21Sep85>
|
|
|
|
MOVE.W VCBXTAlBks(A2),D0 ; Pick up extent B*-Tree size <21Sep85>
|
|
SUB.W D0,ioVNmAlBlks(A0) ; Take out XT allocation <21Sep85>
|
|
MOVE.W VCBCTAlBks(A2),D0 ; Pick up catalog B*-Tree size <21Sep85>
|
|
SUB.W D0,ioVNmAlBlks(A0) ; Take out CT allocation <21Sep85>
|
|
|
|
@25 BTST #HFSBit,ioTrap(A0) ; TFGetVolInfo vs. plain GetVolInfo?
|
|
BNE.S @40 ; Br if it's TGetVolInfo
|
|
|
|
MOVE.W #AlBlkLim,D0 ; Pick up our favorite constant, 32767 <11Oct85>
|
|
CMP.W ioVNmAlBlks(A0),D0 ; Check the number of allocation blocks: <11Oct85>
|
|
BHI.S @30 ; If we're under the limit, we're fine. <11Oct85>
|
|
MOVE.W D0,ioVNmAlBlks(A0) ; Otherwise, pin the value there <11Oct85>
|
|
CMP.W ioVFrBlk(A0),D0 ; Check the number of free blocks: <11Oct85>
|
|
BHI.S @30 ; If we're under the limit, we're fine. <11Oct85>
|
|
MOVE.W D0,ioVFrBlk(A0) ; Otherwise, pin the value there <11Oct85>
|
|
|
|
@30 BRA.S GVIDone
|
|
|
|
; Return some additional information for TGetVolInfo requests:
|
|
|
|
@40 MOVE.W VCBVRefNum(A2),ioVRefNum(A0) ; ALWAYS return VRefNum <25Sep85>
|
|
MOVE.W VCBSigWord(A2),ioVSigWord(A0) ; Volume signature
|
|
MOVE.W VCBDrvNum(A2),ioVDrvInfo(A0) ; Driver number
|
|
MOVE.W VCBDRefNum(A2),ioVDRefNum(A0) ; Driver RefNum
|
|
MOVE.W VCBFSID(A2),ioVFSID(A0) ; File System ID
|
|
CLR.L ioVFilCnt(A0) ; Clear top word
|
|
MOVE.W VCBNmFls(A2),ioVFilCnt+2(A0) ; Stuff low word as if MFS
|
|
CLR.L ioVDirCnt(A0) ; Clear top word
|
|
MOVE.W #1,ioVDirCnt+2(A0) ; Stuff low word as if MFS
|
|
|
|
BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
|
|
BNE.S TGVIOK ; No - the information below doesn't exist
|
|
|
|
MOVE.L VCBVolBkup(A2),ioVBkup(A0) ; Last backup date
|
|
MOVE.W VCBVSeqNum(A2),ioVSeqNum(A0) ; Volume sequence number
|
|
MOVE.L VCBWrCnt(A2),ioVWrCnt(A0) ; Volume write count
|
|
MOVE.L VCBFilCnt(A2),ioVFilCnt(A0) ; Files count for volume
|
|
MOVE.L VCBDirCnt(A2),ioVDirCnt(A0) ; Directory count for volume
|
|
|
|
MOVE.L A0,-(SP) ; Free up A0 as a scratch register
|
|
LEA ioVFndrInfo(A0),A1 ; Destination finder info
|
|
LEA VCBFndrInfo(A2),A0 ; Volume's finder info
|
|
MOVEQ #32,D0 ; Length of finder info
|
|
_BlockMove ; Copy finder info
|
|
MOVE.L (SP)+,A0 ; Restore original A0
|
|
|
|
GVIDone MOVE.L A2,ReqstVol ; Make sure ReqstVol is set up
|
|
|
|
BSR TFSVCBTst ; Are we dealing with a TFS volume? <01Oct85>
|
|
BNE.S TGVIOK ; No - dont' pass to unsuspecting ext. FS
|
|
BSR CkExtFS
|
|
BNE.S TGVIDone
|
|
|
|
TGVIOK MOVEQ #0,D0 ; No errors
|
|
TGVIDone BRA CmdDone
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: SetVolInfo
|
|
; Arguments: A0.L (input) -- I/O PB pointer
|
|
; D0.W (output) -- error code (volume locked, wr prot error)
|
|
; Called By:
|
|
; Function: Change certain user-alterable fields in the VCB
|
|
;
|
|
; Modification History:
|
|
; 14-May-85 PWD New today.
|
|
; 6-Oct-85 PWD Moved SetVolName here from TFSDir2. Changed SetVolInfo to
|
|
; use SetVolName.
|
|
;_______________________________________________________________________
|
|
|
|
SetVolInfo:
|
|
BSR FSQueue ; Wait our turn
|
|
BSR DtrmV1 ; Determine volume by drvnum/refnum
|
|
BNE.S SVIDone ; Punt on errors
|
|
BSR CVFlgs ; Check if volume can be modified
|
|
BNE.S SVIDone ; Give up easily
|
|
BSR ExtOffLinCk ; Check if volume is on-line, non ext. FS
|
|
BNE.S SVIDone ; Be a wimp - give up now.
|
|
|
|
; Set user-modifiable fields in the VCB:
|
|
|
|
MOVE.L IOVCrDate(A0),VCBCrDate(A2) ; Volume creation date
|
|
MOVE.L IOVLsMod(A0),VCBLsMod(A2) ; Date of last modification
|
|
MOVE.W IOVAtrb(A0),D0 ; Volume attributes
|
|
AND.W #$8000,D0 ; Clear all but vol. locked bit
|
|
MOVE.W VCBAtrb(A2),D1 ; Current volume attributes
|
|
AND.W #$7FFF,D1 ; Clear vol. locked bit
|
|
OR.W D0,D1 ; Combine attributes
|
|
MOVE.W D1,VCBAtrb(A2) ; Set new volume attributes
|
|
|
|
BSR TFSVCBTst ; Is it a TFS volume? <01Oct85>
|
|
BNE.S @3 ; br if not - MFS VCBs don't have <01Oct85>
|
|
; this info
|
|
MOVE.L IOVClpSiz(A0),VCBClpSiz(A2) ; Volume clump size
|
|
MOVE.L IOVBkup(A0),VCBVolBkup(A2) ; Last backup date
|
|
MOVE.W IOVSeqNum(A0),VCBVSeqNum(A2); Volume sequence number
|
|
MOVE.L A0,-(SP) ; Save IOPB pointer
|
|
LEA IOVFndrInfo(A0),A0 ; Point to finder info source
|
|
LEA VCBFndrInfo(A2),A1 ; Finder info in VCB
|
|
MOVEQ #32,D0 ; Length of finder info
|
|
_BlockMove ; Copy it in
|
|
MOVEA.L (SP)+,A0 ; Restore IOPB pointer
|
|
|
|
@3 MOVE.L IOVNPtr(A0),D0 ; New name specified?
|
|
BEQ.S @10 ; If not, forget it
|
|
MOVEA.L D0,A1 ; Point to new name <PWD 06Oct85>
|
|
BSR.S SetVolName ; Update name in VCB <PWD 06Oct85>
|
|
@10 BSR MarkVCB
|
|
MOVEQ #0,D0 ; All went well...
|
|
|
|
SVIDone BRA CmdDone
|
|
|
|
SetVolName
|
|
MOVEM.L A1/A2,-(SP) ; Save original VCB pointer
|
|
LEA VCBVN(A2),A2 ; point to 1st char in name destination <PWD 06Oct85>
|
|
MOVEQ #1,D0 ; set up to copy 1st character in name <PWD 06Oct85>
|
|
|
|
@1 CMP.B (A1),D0 ; Exceeded source length? <PWD 06Oct85>
|
|
BGT.S @5 ; If so, call it off <PWD 06Oct85>
|
|
CMP.B #':',0(A1,D0) ; Hit a colon? <PWD 06Oct85>
|
|
BEQ.S @5 ; Yes - punt. <PWD 06Oct85>
|
|
CMP.B #VCBMaxNam,D0 ; Exceeded the max. length? <PWD 06Oct85>
|
|
BGT.S @5 ; Yes - stop here. <PWD 06Oct85>
|
|
MOVE.B 0(A1,D0),0(A2,D0) ; move in new name <PWD 06Oct85>
|
|
ADDQ.W #1,D0 ; Advance to the next character <PWD 06Oct85>
|
|
BRA.S @1 ; And try again <PWD 06Oct85>
|
|
|
|
@5 SUBQ.W #1,D0 ; Back up to real # characters copied <PWD 06Oct85>
|
|
MOVE.B D0,(A2) ; Set new name length <PWD 06Oct85>
|
|
MOVEM.L (SP)+,A1/A2 ; Reset pointer to VCB <PWD 06Oct85>
|
|
BSR MarkVCB ; mark VCB info changed <PWD 06Oct85>
|
|
RTS ; And call it a day
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CVFlgs
|
|
; Arguments: A2.L (input) -- VCB pointer
|
|
; D0.W (output) -- error code (volume locked, wr prot error)
|
|
; Called By:
|
|
; Function: Check the volume's flags to see if modify requests are allowed.
|
|
;
|
|
; Modification History:
|
|
; 08 Dec 82 LAK Changed to support new file system data structures.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
CVFlgs MOVEQ #VLckdErr,D0 ; assume volume locked
|
|
TST.W VCBAtrb(A2) ; volume locked?
|
|
BMI.S CVExit ; br if so
|
|
MOVEQ #WPrErr,D0 ; assume diskette is write protected
|
|
TST.B VCBAtrb+1(A2) ; bit 7=1 means write protected
|
|
BMI.S CVExit ; br if so
|
|
MOVEQ #0,D0 ; otherwise, no error
|
|
CVExit RTS ; that's all folks (BEQ FOR OK)
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: GetVol
|
|
; Arguments: A0.L (input) -- ptr to volume parameter block, uses IOVNPtr,
|
|
; IOVDrvNum
|
|
; D0.W (output) -- error code
|
|
; Calls: FSQueue,CmdDone
|
|
; Function: Find out what the name of the default volume is. The volume
|
|
; name is stored at IOVNPtr(A0). The maximum length
|
|
; of a volume name is 27 bytes. The drive number for the volume
|
|
; is also returned.
|
|
;
|
|
; Modification History:
|
|
; 06 Dec 82 LAK Rewrote to reflect file system data structure changes.
|
|
; Changed to return name of nth volume (0=default).
|
|
; 21 Dec 82 LAK Returns drive number, too.
|
|
; 23 Jan 83 LAK Changed to just return the name of the default volume.
|
|
; 02 Jun 83 LAK Changed to return volume refnum instead of drive number.
|
|
; 30-May-85 PWD Changed to return VRefNum only if drive number of volindex given
|
|
;
|
|
; Test: existing vol name, illegal vol name, etc.
|
|
;_______________________________________________________________________
|
|
|
|
GetVolTrap:
|
|
BTST #HFSBit,D1 ; Check if request is TFS-flavor <04Oct85> PWD
|
|
BNE GetDir ; If so, go to different code altogether<01oct85> BBM
|
|
|
|
BSR FSQueue ; wait for my turn
|
|
|
|
MOVE.L DefVCBPtr,D0 ; ptr to default VCB
|
|
BEQ.S NSVErrXit ; error if no default volume
|
|
MOVEA.L D0,A2 ;
|
|
MOVE.W DefVRefNum,ioVRefNum(A0) ; Return the original default RefNum
|
|
; (which could be a WDRefNum)
|
|
BSR.S XferVName ; Go copy volume name and set D0=0
|
|
GetVolDone BRA CmdDone
|
|
|
|
NSVErrXit MOVEQ #NSVErr,D0
|
|
BRA.S GetVolDone
|
|
|
|
; Quick little routine shared by GetVol, GetVolInfo, GetWDCBInfo: returns
|
|
; the volume name if IOVNPtr(A0) is not zero . . .
|
|
; Returns: D0=0 always . . .
|
|
|
|
XferVName MOVEM.L A1-A2,-(SP) ; Save regs except D0 <31Aug85>
|
|
|
|
LEA VCBVN(A2),A2 ; ptr to vol name
|
|
MOVE.L IOVNPtr(A0),D0 ; ptr to return name buffer
|
|
BEQ.S @3 ; don't return name if pointer is nil
|
|
; AND.L Lo3Bytes,D0 ; let's add in a range check cause <10Dec86>
|
|
; CMP.L MemTop,D0 ; it's a common error to forget to <10Dec86>
|
|
; BGT.S @3 ; fill in the name ptr . . . <10Dec86>
|
|
_StripAddress ; clean up the address before using it <10Dec86>
|
|
MOVE.L D0,A1 ; A1 = cleaned up name buffer ptr
|
|
|
|
MOVEQ #0,D0 ; Clear upper bytes
|
|
MOVE.B (A2),D0 ; len of volume name
|
|
@2 MOVE.B (A2)+,(A1)+ ; move a char of name
|
|
DBRA D0,@2 ; loop until all + 1 done (length too)
|
|
|
|
@3 MOVEM.L (SP)+,A1-A2 ; Restore regs <31Aug85>
|
|
MOVEQ #0,D0 ; Always a success
|
|
RTS
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: SetVol
|
|
; Arguments: A0.L (input) -- ptr to volume parameter block: volume may be
|
|
; specified by either IODrvNum or IOFileName
|
|
; D0.W (output) -- error code
|
|
; All other regs are preserved
|
|
; Calls: DtrmV3
|
|
; Function: Set the current default volume. The volume must be mounted
|
|
; and may be specified by either name or drive number. If neither
|
|
; is specified, the default volume is set to the current value
|
|
; if there is a current default (otherwise an error is reported).
|
|
; The volume name may be followed by a filename (for convenience).
|
|
;
|
|
; Modification History:
|
|
; 06 Dec 82 LAK Rewrote to reflect file system data structure changes.
|
|
; 14 Jan 83 LAK Minor rework.
|
|
; 14-Mar-85 PWD Changed to set up default WDCB
|
|
; 9-Jul-85 PWD Changed to preserve default VRefNum (or WDRefNum) in DefVRefNum
|
|
; 20-Sep-85 PWD Fixed bug in determination of new DefVRefNum when vol. spec'd by name
|
|
; 24-Sep-85 PWD Changed to branch to SetDir when TFS bit is set on trap
|
|
;
|
|
; Test: existing vol name, illegal vol name, etc.
|
|
;_______________________________________________________________________
|
|
|
|
SetVolTrap:
|
|
BTST #HFSBit,D1 ; Check if request is TFS-flavor <02Oct85>
|
|
BNE.S SetDir ; If so, go to different code altogether<24Sep85>
|
|
|
|
BSR FSQueue ; wait for my turn
|
|
BSR DtrmV3 ; determine the volume being asked for
|
|
BNE.S @20 ; br if we couldn't <31Aug85>
|
|
|
|
MOVE.W VCBVRefNum(A2),D0 ; Pick up the new default vol's refNum <20Sep85>
|
|
TST.W D3 ; Was a volume name spec'd? <20Sep85>
|
|
BNE.S @3 ; If so, use its VRefNum straight <20Sep85>
|
|
TST.W ioVRefNum(A0) ; Otherwise, was a driveNum given? <20Sep85>
|
|
BGT.S @3 ; If so, use the VRefNum from the VCB <20Sep85>
|
|
MOVE.W ioVRefNum(A0),D0 ; Pick up the VRefNum supplied
|
|
BEQ.S @5 ; If none was supplied, leave the world as is
|
|
@3 MOVE.W D0,DefVRefNum ; Save this VRefNum/WDRefNum for posterity
|
|
; ... but mostly for GetVol's use
|
|
@5 MOVEQ #FSRtDirID,D6 ; Default directory is the volume's root
|
|
MOVE.L A3,D7 ; Working directory specified (may zero hint)
|
|
BEQ.S @10 ; If not, hint is zeroed, we're all set
|
|
MOVE.L WDDirID(A3),D6 ; Directory ID of working directory
|
|
MOVE.L WDCatHint(A3),D7 ; Catalog hint
|
|
@10 BSR SetDefWDCB ; And go fill in the default WDCB
|
|
MOVEQ #0,D0 ; Return success
|
|
@20 BRA CmdDone ; And call it a day.
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: SetDir
|
|
; Arguments: A0.L (input) -- I/O parameter block
|
|
; D0.W (output) -- error code
|
|
; Called By:
|
|
; Function: Set the default directory (and, implicitly, the default volume).
|
|
;
|
|
; Modification History:
|
|
;
|
|
; 14-Mar-85 PWD New today.
|
|
; 21-Sep-85 PWD Changed to alloc null file names (or just 'vol name:') as well
|
|
; as Nil file name pointers.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
SetDir:
|
|
BSR FSQueue ; Wait for our turn to come
|
|
BSR FndFilName ; Look for the indicated directory
|
|
BEQ.S @0 ; continue if all went well
|
|
|
|
; Special hack to allow MFS volumes to be specified by volume name only (which
|
|
; normally causes FndFilName to choke on the zero-length file name remaining):
|
|
|
|
CMP.W #BdNamErr,D0 ; Was it a bad name? <21Sep85>
|
|
BNE.S SetDirExit ; Nope - give up <21Sep85>
|
|
TST.B D2 ; Yes - 'cuz there wasn't one? <21Sep85>
|
|
BNE.S SetDirExit ; Nope - give up after all <21Sep85>
|
|
MOVEQ #FSRtDirID,D6 ; Yes - OK, use the root on MFS <21Sep85>
|
|
BRA.S SetDefDir ; Yes - that's OK here... <21Sep85>
|
|
|
|
@0 MOVEQ #DirNFErr,D0 ; Let's be pessimistic here
|
|
CMP.B #CDRDirRec,CDRType(A5) ; Was record a directory?
|
|
BNE.S SetDirExit ; Thought so...
|
|
MOVE.L DirDirID(A5),D6 ; DirID to set up = directory's DirID
|
|
;
|
|
; Since SetDir may arrive at the final directory from a pathname relative to a
|
|
; working directory, SetDir cannot simply set DefVRefNum to the WDRefNum supplied,
|
|
; to be returned by GetVol. SetDir ALWAYS stores the real VRefNum, therefore...
|
|
;
|
|
SetDefDir MOVE.W VCBVRefNum(A2),DefVRefNum ; Save this VRefNum for posterity
|
|
; ... but mostly for GetVol's use
|
|
MOVEQ #0,D7 ; No catalog hint known.
|
|
BSR SetDefWDCB ; Set up the default WDCB
|
|
|
|
SetDirOK MOVEQ #0,D0 ; Return success
|
|
|
|
SetDirExit BRA CmdDone ; And that's all, folks!
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: GetDir
|
|
; Arguments: A0.L (input) -- I/O parameter block
|
|
; D0.W (output) -- error code
|
|
; Called By:
|
|
; Function: Get the default volume's name and the current default directory.
|
|
;
|
|
; Modification History:
|
|
;
|
|
; 14-Mar-85 PWD New today.
|
|
; 14-Oct-85 PWD Added call to XferVName now that RetDefInfo doesn't do it anymore
|
|
;_______________________________________________________________________
|
|
|
|
GetDir:
|
|
BSR FSQueue ; Wait our turn
|
|
BSR Gt1stWDCB ; Set up A1, D1 to point at first WDCB <28Aug85>
|
|
MOVEQ #NSVErr,D0 ; Assume no default directory set
|
|
TST.L WDVCBPtr(A1,D1) ; Is this entry actually set up?
|
|
BEQ.S @1 ; If not, we're finished right here & now <28Aug85>
|
|
|
|
BSR RetDefInfo ; Otherwise - return the WDCB information
|
|
BSR XferVName ; Return the name of the associated volume <PWD 14Oct85>
|
|
MOVE.W DefVRefNum,ioVRefNum(A0) ; Return the original default RefNum
|
|
MOVEQ #0,D0 ; A totally stunning success
|
|
|
|
@1 BRA CmdDone ; Call it a day.
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: OpenWD
|
|
; Arguments: A0.L (input) -- I/O parameter block
|
|
; D0.W (output) -- error code
|
|
; Called By:
|
|
; Function: Create a working directory control block from the pathname
|
|
; information in the parameter block.
|
|
;
|
|
; Modification History:
|
|
;
|
|
; 14-Mar-85 PWD New today.
|
|
; 1-Jul-85 PWD Changed to recycle WDRefNums for callers with same procID
|
|
; and return WDRefNum in ioVRefNum field.
|
|
; 21-Sep-85 PWD Changed to allow opening of root of MFS volumes with DirID=2
|
|
; and null or nil filename.
|
|
;_______________________________________________________________________
|
|
|
|
OpenWDTrap:
|
|
BSR FSQueue ; Wait for our turn to come
|
|
BSR FndFilName ; Look for the indicated directory
|
|
BEQ.S @1 ; Br if found
|
|
CMP.W #BdNamErr,D0 ; Was it a bad filename? <21Sep85>
|
|
BNE.S opnWDExit ; If not, there's no more hope <21Sep85>
|
|
TST.B D2 ; Otherwise, check the name length <21Sep85>
|
|
BNE.S opnWDExit ; If nonzero, it's real BdNamErr <21Sep85>
|
|
BRA.S @2 ; Return VRefNum for MFS null file names<21Sep85>
|
|
|
|
@1 MOVEQ #DirNFErr,D0 ; Let's be pessimistic here
|
|
CMP.B #CDRDirRec,CDRType(A5) ; Was record a directory?
|
|
BNE.S opnWDExit ; Thought so...
|
|
|
|
MOVE.L DirDirID(A5),D6 ; DirID to set up = directory's DirID
|
|
CMP.L #FSRtDirID,D6 ; Accessing the root? <21Sep85>
|
|
BEQ.S @2 ; Nope - create a real new WDCB <21Sep85>
|
|
|
|
MOVEQ #0,D7 ; No catalog hint known.
|
|
BSR.S PickWDCB ; Look for a suitable WDCB
|
|
BRA.S opnWDExit
|
|
|
|
@2 MOVE.W VCBVRefNum(A2),ioVRefNum(A0) ; Return the VRefNum as WDRfn <21Sep85>
|
|
|
|
opnWDOK MOVEQ #0,D0 ; Call it a success <21Sep85>
|
|
opnWDExit BRA CmdDone ; we're finished . . .
|
|
|
|
SetDefWDCB MOVE.L A2,DefVCBPtr ; set the (new?) default
|
|
MOVEQ #2,D1 ; Pick the default-WDCB
|
|
|
|
FillWDCB MOVE.L WDCBsPtr,A1 ; Point to the WDCB array
|
|
MOVE.L A2,WDVCBPtr(A1,D1.W) ; Set the default VCB
|
|
MOVE.L D6,WDDirID(A1,D1.W) ; In the default WDCB
|
|
MOVE.L D7,WDCatHint(A1,D1.W) ; Catalog hint for this directory
|
|
MOVE.L ioWDProcID(A0),D0 ; Pick up caller's procID
|
|
MOVE.L D0,WDProcID(A1,D1.W) ; Mark WDCB with it
|
|
ADD.W #WDRfnMin,D1 ; Offset into the WDCB Refnum range
|
|
RTS ; And return it to the caller
|
|
|
|
; Look for a matching working directory, starting with the third (the first two are
|
|
; reserved to hold the system-wide volume and directory defaults).
|
|
|
|
EXPORT PickWDCB ; <SM4> rb
|
|
PickWDCB:
|
|
MOVEA.L A2,A5 ; A5 <> 0, MF is not running flag (A2 <> 0)
|
|
|
|
;; A0=iopb, A2=VCB, D3.L=ProcID, D6.L=DirID, D7.L=0. A3,A4,D2,D4,D5 are free.
|
|
;; A5.L=caller's procID because I run out of D regs ...
|
|
MOVEA.L FSVarsPtr,A3
|
|
MOVEa.L FSVars.wdcbPBuf(A3),A3 ; A3=WDCB parallel array
|
|
MOVE cbPBufULen(A3),D3 ; D3=Ext. WDCB unit length
|
|
LEA wdcbPBufData(A3),A3 ; skip info words (A3 = 1st WDCB)
|
|
MOVEA.L A3,A4 ; A4 = 1st WDCB
|
|
ADDA D3,A3 ; A3 = 2nd WDCB
|
|
MOVEQ #0,D4 ; ID1= 0
|
|
MOVEQ #0,D5 ; ID2= 0 (no serial ID)
|
|
BSR ProcessMgrExists ; check Process Mgr ready?
|
|
BNE.S @nomf ; no, don't bother with serial ID
|
|
;; Process Mgr is available, we are open for business
|
|
SUBA.L A5,A5 ; A5=0 if MultiFinder is ready <06Aug90>
|
|
MOVE.L A0,-(SP) ; save iopb
|
|
LEA -10(SP),SP ; make room for PSN and OSErr
|
|
PEA 2(SP) ; push address of PSN storage
|
|
_GetSystemClientProcess ; call OS (can trash pascal registers)
|
|
LEA 2(SP),SP ; don't need to check for error
|
|
MOVE.L (SP)+,D4 ; D4 = process ID1
|
|
MOVE.L (SP)+,D5 ; D5 = process ID2
|
|
MOVEA.L (SP)+,A0 ; restore iopb
|
|
|
|
@nomf: MOVEQ #0,D2 ; Clear free WDCB index
|
|
jsr Gt1stWDCB ; Set up A1, D1 (point at first WDCB)
|
|
jsr GtNxtWDCB ; Point at 2nd WDCB
|
|
; (A1,D1)=WDCB, D2=freeRefNum,
|
|
@1 ADDA D3,A3 ; Point at next Extended WDCB
|
|
jsr GtNxtWDCB ; Point at next (3rd) WDCB
|
|
BCC.S @3 ; Br if we've seen them all
|
|
TST.L WDVCBPtr(A1,D1) ; Is this WDCB free?
|
|
BNE.S @2 ; If NE, no
|
|
TST.W D2 ; Already found a free one?
|
|
BNE.S @1 ; Yes - continue scan
|
|
MOVE.W D1,D2 ; No - hang on to this WD index
|
|
BRA.S @1 ; And continue scanning
|
|
|
|
@2 CMP.L WDVCBPtr(A1,D1),A2 ; For same volume?
|
|
BNE.S @1 ; Nope - keep looking
|
|
CMP.L WDDirID(A1,D1),D6 ; Same directory?
|
|
BNE.S @1 ; Nope - keep looking
|
|
|
|
MOVE.L A5,D0 ; MF ready? <06Aug90>
|
|
BEQ.S @mfON ; yes, check serial number <06Aug90>
|
|
;; MultiFinder is not ready, check wdProcID <06Aug90>
|
|
MOVE.L ioWDProcID(A0),D0 ; Pick up owner's ProcID <06Aug90>
|
|
CMP.L WDProcID(A1,D1.W),D0 ; same ProcID? <06Aug90>
|
|
BNE.S @1 ; Nope - sigh. <06Aug90>
|
|
BRA.S @wdFnd ; found it <06Aug90>
|
|
|
|
@mfON CMP.L xWDCBPid2(A3),D5 ; For same owner?
|
|
BNE.S @1 ; Nope - sigh.
|
|
CMP.L xWDCBPid1(A3),D4 ; For same owner?
|
|
BNE.S @1 ; Nope - sigh.
|
|
|
|
@wdFnd ;; Recycle the WD RefNum:
|
|
CLR ioWDCreated(A0) ; say we are not creating one <10/9/89>
|
|
ADDI #WDRfnMin,D1 ; Offset the index to make a WDRefNum
|
|
BRA.S @4 ; Return the current WDRefNum
|
|
|
|
; Use a new WDCB:
|
|
|
|
@3 MOVE.W D2,D1 ; Free WDCB found?
|
|
BEQ.S pickNoMore ; Nope - die.
|
|
MOVE #1,ioWDCreated(A0) ; we are creating a new one <10/9/89>
|
|
;; Now A1 --> WDCBs, D1.W = WDrefnum, A4 = 1st Ext. WDCB, D4,D5=ID, D6=DirID, D7=hint
|
|
MOVEQ #0,D0
|
|
MOVE D1,D0 ; D0=WDRefNum
|
|
MOVE #WDCBLen,D3 ; D3 = WDCB len
|
|
DIVU D3,D0 ; Divide by length to get WDCB's number
|
|
LSL #L2ExtWDCBLen,D0 ; index into the extended FCB
|
|
MOVE.L D4,xWDCBPid1(A4,D0) ; save it
|
|
MOVE.L D5,xWDCBPid2(A4,D0) ; save it
|
|
|
|
jsr FillWDCB ; user's ProcID data still stored in WDCB by this call
|
|
|
|
@4 MOVE.W D1,IOVRefNum(A0) ; Store in user's I/O parameter block
|
|
MOVEQ #0,D0 ; Total success
|
|
RTS ;
|
|
|
|
pickNoMore MOVEQ #TMWDOErr,D0 ; No WDCBs are free: fail miserably
|
|
RTS
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CloseWD
|
|
; Arguments: A0.L (input) -- I/O parameter block
|
|
; D0.W (output) -- error code
|
|
; Called By:
|
|
; Function: Release the storage used for a working directory control block.
|
|
;
|
|
; Modification History:
|
|
;
|
|
; 14-Mar-85 PWD New today.
|
|
; 1-Jul-85 PWD Changed to do away with VCBWDCnt maintenance
|
|
; Changed to take WDRefNum in ioVRefNum field.
|
|
; 6-Aug-85 PWD Changed to call external FS (WITHOUT clearing WDCB!)
|
|
; 20-Aug-85 PWD Changed to make VRefNum arg a no-op.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
CloseWDTrap:
|
|
BSR FSQueue ; Wait for our turn to come
|
|
MOVEQ #0,D1 ; Clear top half of D1
|
|
MOVE.W IOVRefNum(A0),D1 ; Pick up the WDRefNum
|
|
BSR CkWDRefNum ; Check if it's OK for use, set up A1=WDCBSptr <31Aug85>
|
|
BEQ.S @1 ; Br if so
|
|
|
|
CMP.W #WDRfnMax,D1 ; Is it a VRefNum? <20Sep85>
|
|
BHI.S clsWDOK ; OK HI ($F000-$FFFF) . . . (assume valid VRefNum)
|
|
BRA.S clsWDExit ; Punt on errors
|
|
|
|
; The refnum provided checked out OK:
|
|
|
|
@1 SUB.W #WDRfnMin,D1 ; Offset to change to WD array index
|
|
MOVEA.L WDVCBPtr(A1,D1),A2 ; Pick up volume referred to
|
|
TST.W VCBFSID(A2) ; Mac FS?
|
|
BEQ.S @2 ; Yes - please continue
|
|
MOVE.L A2,ReqstVol ; No - indicate such to the external FS
|
|
ADD.L A1,D1 ; Point D1 to WDCB
|
|
MOVEQ #ExtFSErr,D0 ; And leave this one alone
|
|
BRA.S clsWDExit ;
|
|
|
|
@2 CLR.L WDVCBPtr(A1,D1) ; Clear the VCB pointer to free the WDCB
|
|
|
|
clsWDOK MOVEQ #0,D0 ; Success at last!
|
|
clsWDExit BRA CmdDone ; Leave by common exit
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: GetWDInfo
|
|
; Arguments: A0.L (input) -- I/O parameter block
|
|
; D0.W (output) -- error code NSVErr = couldn't find it
|
|
; Called By:
|
|
; Function: Read the information in a WDCB for a given volume.
|
|
;
|
|
; Modification History:
|
|
;
|
|
; 1-May-85 PWD New today.
|
|
; 1-Jul-85 PWD Changed to match procID on indexed requests.
|
|
; 6-Aug-85 PWD Changed to call external FS for ext. FS volumes AFTER
|
|
; copying volume information.
|
|
; 22-Aug-85 PWD Changed to return root information for requests by RefNum
|
|
; <28Aug85> LAK Fixed bug in indexed get. Now allows specification by
|
|
; default volume even, or drive number . . . why not? No
|
|
; more ParamErr, it's NSVErr or it's ok.
|
|
;_______________________________________________________________________
|
|
|
|
GetWDInfoTrap:
|
|
BSR FSQueue ; Wait our turn
|
|
BSR.S GetWDCBInfo ; Return the WDCB information <PWD 14Oct85>
|
|
BNE.S GtWDIExit ; Punt on errors <PWD 14Oct85>
|
|
|
|
EXT.L D1
|
|
ADD.L A1,D1 ; Point D1 to WDCB for extFS
|
|
MOVE.L A2,ReqstVol ; in case of extFSErr
|
|
BSR CkExtFS ; Is this an external file system volume? <PWD 14Oct85>
|
|
BNE.S GtWDIExit ; br if not (pass D1=WDCB ptr or 0 if not a WDCB)
|
|
GtWDIOK MOVEQ #0,D0 ; Otherwise, a total success
|
|
GtWDIExit BRA CmdDone ; And call it a day. <PWD 14Oct85>
|
|
|
|
;
|
|
; Subroutine shared between _GetWDInfo (queuing) and _ReadWDCB (non-queueing): <PWD 14Oct85>
|
|
;
|
|
GetWDCBInfo TST.W ioWDIndex(A0) ; Test working dir index
|
|
BGT.S IndxWDInfo ; If positive, look up WD by index/volume
|
|
|
|
; Return information for a specific Working Directory, indicated by RefNum:
|
|
|
|
MOVEQ #0,D1 ; CkWDRefNum needs high word of D1 inited to zero <15APR86> PWD
|
|
MOVE.W IOVRefNum(A0),D1 ; Pick up a WDRefNum/VRefNum
|
|
BSR CkWDRefNum ; Check its integrity (trashes D0, sets A1=WDCBsPtr)
|
|
BEQ.S getWD_1 ; br if it's a valid WDCB refnum <22Aug85>
|
|
|
|
BSR DtrmV1 ; Does VRefNum specify a valid volume? <22Aug85>
|
|
BNE.S GetWDIExit ; Give up easily <22Aug85>
|
|
|
|
; By special arrangement, calling _GetWDInfo with a VRefNum will fill out <22Aug85>
|
|
; a working directory arrangement for the root: <22Aug85>
|
|
|
|
CLR.L ioWDProcID(A0) ; No proc. id's defined for system <22Aug85>
|
|
MOVEQ #FSRtDirID,D0 ; <22Aug85>
|
|
MOVE.L D0,ioWDDirID(A0) ; Pick up the volume's root directory ID<22Aug85>
|
|
MOVE.W VCBVRefNum(A2),ioWDVRefNum(A0) ; Return the volume's refNum <22Aug85>
|
|
MOVE.W VCBVRefNum(A2),ioVRefNum(A0) ; for both fields . . . <22Aug85>
|
|
MOVEQ #0,D1 ; no WDCB ptr for extFS . . . <28Aug85>
|
|
BRA.S XferVN ; proceed to return the name (pass A2) <22Aug85>
|
|
|
|
; WD refnum was supplied and ioWDIndex<=0, so return a specific entry . . .
|
|
|
|
getWD_1
|
|
MOVEQ #NSVErr,D0 ; Let's just assume thing's aren't cool
|
|
SUB.W #WDRfnMin,D1 ; Change refNum to index
|
|
TST.L WDVCBPtr(A1,D1) ; This entry really in use?
|
|
BEQ.S GetWDIExit ; Nope - too bad.
|
|
BRA.S XferWDInfo ; Yes - fill in the info (pass A1, D1)
|
|
|
|
IndxWDInfo
|
|
MOVEQ #NSVErr,D0 ; Let's be pessimistic for a moment...
|
|
MOVEQ #0,D2 ; assume no volume match
|
|
TST.W IOVRefNum(A0) ; Was a VRefNum supplied?
|
|
BEQ.S @1 ; Nope - go for it
|
|
BSR DtrmV3 ; Find the VCB
|
|
BNE.S GetWDIExit ; Punt if no volume found
|
|
MOVE.L A2,D2 ; Stash VCB pointer
|
|
|
|
; Try to find the requested WDCB:
|
|
|
|
@1 MOVE.W ioWDIndex(A0),D4 ; Get a hold of the working dir. index
|
|
MOVE.L ioWDProcID(A0),D3 ; Pick up the caller's procID, if any
|
|
|
|
MOVEQ #NSVErr,D0 ; Start out pessimistic
|
|
BSR Gt1stWDCB ; Set up A1, D1 (point at first WDCB)
|
|
BSR GtNxtWDCB ; Point at 2nd WDCB
|
|
|
|
getWDLoop BSR GtNxtWDCB ; Point at next WDCB (the first two WDCBs are not counted)
|
|
BCC.S GetWDIExit ; Br if we've seen them all
|
|
TST.L WDVCBPtr(A1,D1) ; Is this WDCB in use?
|
|
BEQ.S getWDLoop ; If EQ, it's not (only count the used ones)
|
|
|
|
TST.L D3 ; Match on procID?
|
|
BEQ.S @1 ; If not, don't bother checking
|
|
CMP.L WDProcID(A1,D1),D3 ; Is it for this caller?
|
|
BNE.S getWDLoop ; If no match, it's not
|
|
|
|
@1 TST.L D2 ; Match on volume?
|
|
BEQ.S @2 ; No - this WDCB is OK
|
|
CMP.L WDVCBPtr(A1,D1),D2 ; Yes - for requested volume?
|
|
BNE.S getWDLoop ; If not, skip it.
|
|
|
|
@2 SUBQ.W #1,D4 ; Count down: one done
|
|
BGT.S getWDLoop ; Keep going until the right one's found
|
|
|
|
XferWDInfo BSR.S RetWDInfo ; Copy out the Working directory information
|
|
XferVN BSR XferVName ; Copy volume name (sets D0) <PWD 14Oct85>
|
|
GetWDIExit TST.W D0 ; Set condition codes <PWD 14Oct85>
|
|
RTS ; And call it a day. <PWD 14Oct85>
|
|
|
|
ReadWDCB: MOVEM.L D3-D7/A1-A6,-(SP) ; Save registers [normally done in FSQueue] <PWD 14Oct85>
|
|
MOVEA.L HFSStkTop,A6 ; Set up A6 for use as stack pointer <PWD 14Oct85>
|
|
BSR GetWDCBInfo ; Pick up the WDCB information requested <PWD 14Oct85>
|
|
MOVEM.L (SP)+,D3-D7/A1-A6 ; Restore scratch registers [normally CmdDone] <PWD 14Oct85>
|
|
MOVE.W D0,IOResult(A0) ; post result code <PWD 14Oct85>
|
|
RTS ; Call it a day <PWD 14Oct85>
|
|
|
|
; Small routine to transfer the information of interest:
|
|
; (RetDefInfo called by GetDir)
|
|
; Expects: A1,D1
|
|
; Returns: A2=WDVCBPtr(A1,D1)
|
|
; Blows: D0
|
|
|
|
RetWDInfo: ; GetWDInfo entry
|
|
MOVE.L WDProcID(A1,D1),ioWDProcID(A0) ; Copy ProcID (NOT FOR GETDIR . . .)
|
|
RetDefInfo: ; GetDir entry
|
|
MOVEA.L WDVCBPtr(A1,D1),A2 ; Point to VCB for associated volume
|
|
MOVE.W VCBVRefNum(A2),ioWDVRefNum(A0) ; Copy VRefNum
|
|
MOVE.L WDDirID(A1,D1),ioWDDirID(A0) ; Copy WD's DirID
|
|
|
|
MOVE.W D1,D0 ; use D0 as scratch <31Aug85>
|
|
ADD.W #WDRfnMin,D0 ; Convert index back to WD RefNum <31Aug85>
|
|
MOVE.W D0,ioVRefNum(A0) ; And return it to the user <31Aug85>
|
|
RTS ; Call it a day <14Oct85>
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CkWDRefNum
|
|
; Arguments: D1.L (input) -- WDCB RefNum (top half should be 0)
|
|
; D0.W (output) -- 0 for success, or RFNumErr
|
|
; A1.L (output) -- WDCBsPtr
|
|
; Called By:
|
|
; Function: A quick common routine to check a WDCB refnum for validity.
|
|
;
|
|
; Modification History:
|
|
;
|
|
; 1-May-85 PWD New today.
|
|
; <28Aug85> LAK Some short branches, please. Also removed redundant check
|
|
; against min and max (this is accomplished by the unsigned
|
|
; compare against index bounds).
|
|
; <15Sep86> BB Added check for a zero VCB pointer in the WDCB indicating
|
|
; that the WD is already closed.
|
|
;_______________________________________________________________________
|
|
;
|
|
CkWDRefNum MOVE.L D1,-(SP) ; Save D1 across the call <29Aug85>
|
|
MOVEQ #RFNumErr,D0 ; Let's just assume thing's aren't cool
|
|
|
|
SUB.W #WDRfnMin,D1 ; Offset to zero
|
|
MOVEA.L WDCBsPtr,A1 ; Point to the WDCB array
|
|
CMP.W (A1),D1 ; Pointing beyond the end?
|
|
BCC.S WDRfnCkExit ; Yes - bad news. <28Aug85>
|
|
|
|
SUBQ.W #2,D1 ; Compensate for the length word
|
|
DIVU #WDCBLen,D1 ; Divide by the length of a WDCB
|
|
SWAP D1 ; Get a hold of the remainder
|
|
TST.W D1 ; Check if it's zero
|
|
BNE.S WDRfnCkExit ; Unmasked at last! <28Aug85>
|
|
|
|
MOVE.L (SP),D1 ; WD RefNum <15Sep86>
|
|
SUB.W #WDRfnMin,D1 ; Offset to zero <C193>
|
|
TST.L WDVCBPtr(A1,D1) ; check VCB pointer <15Sep86>
|
|
BEQ.S WDRfnCkExit ; its zero, WD is aready closed <15Sep86>
|
|
|
|
MOVEQ #0,D0 ; OK - all seems well.
|
|
|
|
WDRfnCkExit MOVE.L (SP)+,D1 ; Restore original D1 value <29Aug85>
|
|
TST.W D0 ; Set CCR <28Aug85>
|
|
RTS
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: SetUpWDCB, SetupDef
|
|
; Arguments: A0.L (input) -- I/O Parameter block
|
|
; Uses: ioVRefNum - Volume to refer to
|
|
; ioDirID - Directory of choice
|
|
; ioWDProcID - Caller's procID
|
|
;
|
|
; D0.W (output) -- error code, or 0 for success
|
|
; ioVRefNum(A0) -- Updated with WDRefNum if D0 = 0 on output.
|
|
; (from SetUpWDCB)
|
|
; Called By:
|
|
; Function: A low-level routine to set up a WDCB, or the default WDCB
|
|
; in particular
|
|
;
|
|
; Modification History:
|
|
;
|
|
; 22-May-85 PWD New today.
|
|
; 26-Sep-85 PWD Added SetupDef entry point for external FS support.
|
|
;_______________________________________________________________________
|
|
|
|
; NOTE: This code executes under special conditions: since it does NOT call
|
|
; FSQueue on entry, A6 is never set up; any code called from this routine
|
|
; cannot rely on A6 being set. Furthermore, it does NOT provide the
|
|
; standard full-fledged file finding: VRefNum/DirID is the ONLY valid input.
|
|
|
|
SetUpWDCB:
|
|
MOVEM.L D3-D7/A1-A6,-(SP) ; Save registers (not done in FSQueue now...)
|
|
MOVEA.L HFSStkTop,A6 ; Set up A6 for use as stack pointer <PWD 14Oct85>
|
|
BSR DtrmV1 ; Determine the volume of choice
|
|
BNE.S SetWDExit ; Punt on errors
|
|
MOVE.L ioDirID(A0),D6 ; Requested DirID
|
|
MOVEQ #0,D7 ; No known catalog hint
|
|
BSR PickWDCB ; Select and fill a WDCB, or
|
|
BNE.S SetWDExit ; ... bail out with an error
|
|
|
|
MOVE.W D1,ioVRefNum(A0) ; Return a WDRefNum, because
|
|
SetWDOK MOVEQ #0,D0 ; ... All went well
|
|
|
|
SetWDExit MOVEM.L (SP)+,D3-D7/A1-A6 ; Restore scratch registers
|
|
MOVE.W D0,ioResult(A0) ; Set up result code <PWD 14Oct85>
|
|
RTS ; And call it a day.
|
|
; [returns directly to trap dispatcher]
|
|
|
|
SetupDef: MOVEM.L D3-D7/A1-A6,-(SP) ; Save registers, same as SetUpWDCB <26Sep85>
|
|
MOVEA.L HFSStkTop,A6 ; Set up A6 for use as stack pointer <PWD 14Oct85>
|
|
BSR DtrmV1 ; Determine volume by refNum/driveNum <26Sep85>
|
|
BNE.S SetWDExit ; Punt on errors <26Sep85>
|
|
MOVE.W VCBVRefNum(A2),DefVRefNum ; Save this one for posterity <26Sep85>
|
|
MOVE.L ioDirID(A0),D6 ; Requested DirID <26Sep85>
|
|
MOVEQ #0,D7 ; No hint known <26Sep85>
|
|
BSR SetDefWDCB ; Set up the full default WDCB <26Sep85>
|
|
BRA.S SetWDOK ; And call it a day <26Sep85>
|
|
; [returns directly to trap dispatcher] <26Sep85>
|
|
|