mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-15 12:30:53 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
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>
|
|
|