mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-26 01:49:19 +00:00
1612 lines
66 KiB
Plaintext
1612 lines
66 KiB
Plaintext
;
|
||
; File: DeviceMgr.a
|
||
;
|
||
; Contains: This module contains the core routines that form the kernel of the
|
||
; I/O system. These include OPEN, CLOSE, READ, CONTROL, STATUS, KILLIO,
|
||
; DRVRINSTALL, and DRVRREMOVE. They receive control from the core routine
|
||
; dispatcher and pass control to the file system or I/O drivers.
|
||
;
|
||
; Written by: Andy Hertzfeld
|
||
;
|
||
; Copyright: © 1981-1992 by Apple Computer, Inc., all rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM8> 10/29/92 SWC Changed SlotEqu.a->Slots.a.
|
||
; <SM7> 10/26/92 CSS Change some branch short instructions to branches. Plus
|
||
; removed cache flushes from this file and put them in the
|
||
; file manager (TFSRFN1.a).
|
||
; <SM6> 5/21/92 kc Append "Trap" to the names of
|
||
; Control,Status,KillIO,AddDrive,Enqueue and Dequeue to avoid name
|
||
; conflict with the glue.
|
||
; <SM5> 5/17/92 kc Remove "WITH PmgrRec."
|
||
; <SM4> 4/14/92 kc Remove the ClosePatch rolled in revision <SM2>
|
||
; <SM3> 4/7/92 RB Rolled in OpenIgnorePatch from DeviceMgrPatches.a in Terror. It
|
||
; clears the result code after calling UpdateSRT from the Slot
|
||
; Mgr, in the Open call.
|
||
; <SM2> 2/13/92 PN Roll in ClosePatch from FileMgrPatches.a.
|
||
; <SM1> • Pre-SuperMario comments follow •
|
||
; <13> 12/30/91 RB OOps, I accidentally commented out a label...
|
||
; <12> 12/30/91 RB Updated to reflect Terror. Got rid of the 040 cache flush code
|
||
; since it is supposed to be done by the file system.
|
||
; <11> 10/18/91 JSM Get rid of all the stupid conditionals.
|
||
; <10> 10/1/91 JSM Commented out code that used eclipseDebug.
|
||
; <9> 9/30/91 JSM Don’t use is32BitClean conditional, all future ROMs will be.
|
||
; <8> 8/29/91 JSM Cleanup header.
|
||
; <7> 6/12/91 LN Changed #include 'HardwareEqu.a' to 'HardwarePrivateEqu.a'
|
||
; <6> 3/13/91 bbm &CCH; fix hard instruction cpusha to a call to jCacheFlush
|
||
; <5> 9/18/90 BG Removed EclipseNOPs and modified <4> to not be conditionalized
|
||
; for EclipseDebug. Left the conditionalization in -Write- but it
|
||
; will need to be fixed correctly sometime soon.
|
||
; <4> 6/18/90 CCH Added a cache flush in the postcompletion routine and some NOPs
|
||
; for 68040 machines.
|
||
; <3> 3/29/90 MSH Add universal run time test of IdleUpdate call.
|
||
; <2> 3/20/90 PWD Fix to Open to check FSFCBLen before calling the file system.
|
||
; This fixes a crash if an open @boot time doesn't find the driver
|
||
; in the rom resource map or slots.
|
||
; <2.1> 11/1/89 MSH Rolling in changes from HcMac Reality sources: Pmgr equates now
|
||
; record based.
|
||
; <2.0> 8/22/89 SES Removed references to nFiles. Changed include DeclRomEqu.a to
|
||
; RomEqu.a.
|
||
; <1.9> 6/12/89 djw Removed special case of setting slot zero video base in open
|
||
; <1.8> 6/11/89 GGD Get Slot zero video ram base from rom tables.
|
||
; <1.7> 5/29/89 GGD Added runtime test to support slot zero only if RBV exists.
|
||
; <1.6> 5/1/89 CSL one more ,Sys for another Recoverhandle
|
||
; <1.5> 4/28/89 CSL Fixed vGoDriver, ,Sys required for calling recoverhandle
|
||
; <1.4> 2/20/89 rwh more feature-based conditional changes. Also re-spelled some
|
||
; <1.3> 2/17/89 CSL made IOCore 32 bit friendly, soon be optimized using memory
|
||
; manager vector.
|
||
; <1.2> 1/30/89 GGD Added unconditional call to CacheFlush in _Read, to allow better
|
||
; support for 68020/030s in the 68000 ROMs. Changed several
|
||
; on-NuMac|on-MvMac to has-SlotMgr conditional.
|
||
; <1.1> 11/10/88 CCH Fixed Header.
|
||
; <1.0> 11/9/88 CCH Adding to EASE.
|
||
; <1.4> 11/7/88 djw Special case slot zero to set dCtlDevBase field in OPEN
|
||
; <•1.3> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles
|
||
; <1.2> 9/8/88 MSH New, improved method for Idle/Sleep support.
|
||
; <1.1> 4/18/88 CSL Add support for sleep and idle in READ & WRITE
|
||
; <1.1> 4/18/88 CSL Support Sleep and Idle for HcMac in READ & WRITE.
|
||
; <1.0> 2/10/88 BBM Adding file for the first time into EASE…
|
||
; <C950> 11/8/87 DAF Added slot driver version test to Open (rolled in from patches)
|
||
; <C914> 10/29/87 rwh Port to Modern Victorian
|
||
; <C883> 9/10/87 CSL Do _stripaddress for address masking
|
||
; <C887> 9/9/87 GWN SDM 32-bit mode fix: Use sFindBigDevBase or sFindDevBase to
|
||
; determine the device base.
|
||
; <C805> 2/12/87 RDC Added copyright notice, hooks to various routines
|
||
; <C787> 2/11/87 GWN If no slot driver, then go to FSOpen.
|
||
; <C750> 2/3/87 GWN Cleaned up the UT grow code.
|
||
; <C668> 1/22/87 bbm added a vector to flush the cache in Read.
|
||
; <C671> 1/22/87 GWN cleared field before _sUpdateSRT.
|
||
; <C657> 1/20/87 GWN Renamed sDetDevBase to sFindDevBase.
|
||
; <C632> 1/14/87 DAF Fixed Open to correctly look for drivers
|
||
; <C620> 1/13/87 GWN Use ioFlags+1 in isSlotDrvr and made some code review changes.
|
||
; <C600> 1/7/87 GWN Made changes for slot booting. Changed the parameter block for
|
||
; _Open.
|
||
; <C540> 12/18/86 JSP added test of D0 after stripaddress in routine MpUnitNum.
|
||
; <C542> 12/18/86 GWN Using _sUpdateSRT to update the SRT.
|
||
; <C539> 12/17/86 GWN removed spDrvrType.
|
||
; <C537> 12/16/86 GWN Bug: ioDevice(An) loaded using wrong address register.
|
||
; <C523> 12/14/86 GWN Added support for booting from slots (ioDevice & dctlExtDev).
|
||
; Also added code to allow UT to grow in increments of 5 entries.
|
||
; <C521> 12/13/86 DAF Adjusted Open to look in systemFile first, then slotROM, then
|
||
; ROMResources (until we kill the TFB1K card)
|
||
; <C504> 12/11/86 GWN Replaced _sFindsRsrcList with _sRsrcInfo.
|
||
; <C482> 12/4/86 bbm The code to flush the cache in read needed to be set in
|
||
; conditionals for on-NuMac.
|
||
; <C456> 11/22/86 bbm moved the code to flush the cache into blockmove, loadseg,
|
||
; unloadseg, and read. this might improve performance.
|
||
; <C334> 11/21/86 JSP Added address stripping within IODone for dce pointer passed in.
|
||
; Also cleaned up some usage of stripping off top eight bytes for
|
||
; address soundness. All changes are conditionally assembled since
|
||
; Alladin ROM is frozen and we don't to affect their checksum!
|
||
; <C331> 11/2/86 RDC Added fix for new equ name for slot mgr flag
|
||
; <C226> 10/10/86 GWN Added code to update the Slot Resource table at Open and Close
|
||
; time.
|
||
; <C206> 10/9/86 bbm Modified to mpw aincludes.
|
||
; <C169> 9/29/86 JTC Leaving in pseudo-RecoverHandle (two of them) and one
|
||
; StripAddress to gain speed during interrupt processing. Thus,
|
||
; this code is NOT 32-bit friendly.
|
||
; <C169> 9/25/86 JTC 32-bit support through HLock, HUnlock, etc.
|
||
; <C133> 8/29/86 GWN Changed Open to support slot drivers. Extended DCE for slots.
|
||
; DCE is initialized with Slot, Id and DeviceBase. Also, Open's
|
||
; parameter block has been extended to pass more parameters for
|
||
; slots and in general. The new parameters are ioMix, ioFlags,
|
||
; ioSlot, ioId and ioDevice. Finally, since an extra A-register
|
||
; was used in open, many movem's were changed since routines can
|
||
; exit anywhere (For example close exits via open).
|
||
; <C54> 6/24/86 WRL Changed access to ROMBase to make it survive a 32 bit value.
|
||
; 2/19/86 BBM Made some modifications to work under MPW
|
||
; 1/13/86 LAK Incorporated ROM75Fix patch to IODone.
|
||
; 11/1/85 LAK Only check IOPermssn (not IOFileType) for $40 at Open to discern
|
||
; OpenDeskAcc calls (allows passing IOFileType=1 to MacVision).
|
||
; GetNamedResource 'ResNotFound' errors in ResErr passed to File
|
||
; System
|
||
; 10/4/85 LAK Only refuse to close if CloseErr is passed back (compatibility
|
||
; reasons - print code was often passing back an error causing it
|
||
; to screw up later). Driver is marked open before call to driver
|
||
; open routine and marked closed if open fails (some drivers like
|
||
; to call close on themselves on error conditions and expect to be
|
||
; called: they won't be if they look closed). If GetNamedRes fails
|
||
; at open due to other than ResNotFnd errors (e.g., memfullerr),
|
||
; no longer goes on to file system (used to result in an FNFErr).
|
||
; 7/24/85 RDC Changed interrupt masking to use equates Added separate include
|
||
; statement for HWequ (no longer in systlqk.sym)
|
||
; 7/10/85 LAK Set up ROMMapInsert before GetNamedResource and GetResInfo in
|
||
; Open.
|
||
; 6/27/85 LAK Minor change to mark driver open AFTER the GoDriver Open call
|
||
; instead of before.
|
||
; 5/20/85 LAK Open now calls GetResInfo with nils for name and type var
|
||
; params; calls DrvrInstall ,LOCK if driver has 'needs lock' bit
|
||
; set in it. DrvrInstall looks at new 'asyncTrpBit' and reserves
|
||
; mem low for the DCE if it's set ('LOCK' bit). Adjusted Async
|
||
; driver to use it.
|
||
; 5/5/85 JTC Change to return long error code in D0. Summary <05Jun85> Fetch,
|
||
; Stash: Aren't dispatched, so don't really care, but an extend
|
||
; added for consistency. PostCompletion: extended for consistency.
|
||
; IODone: passes through whatever it's sent in D0. Read, Write,
|
||
; Control, Status, Close: changed in IORWCS and GoDriver to extend
|
||
; to long. KillIO: already long. DrvrInstall, DrvrRemove: extend
|
||
; to long.
|
||
; 5/2/85 LAK Very very minor PostCompletion change: turn positive result
|
||
; codes to 0 instead of negating them (just to be consistent).
|
||
; 4/9/85 LAK Very minor tweak to close (treat only negative numbers as error
|
||
; codes).
|
||
; 3/19/85 LAK Call driver-open for desk accessories even if they are already
|
||
; opened (they are used to this). Quick fix added to KillIO to
|
||
; avoid driver call if it's not Open or enabled for Control calls.
|
||
; 3/14/85 LAK Made all positive Open driver call D0 values = successful Open.
|
||
; This should break fewer drivers.
|
||
; 3/6/85 LAK Return D0 error code for AddDrive.
|
||
; 2/20/85 LAK Don't compact heap before lock of driver which needs lock (why
|
||
; pay the performance penalty? driver should have locked bit set
|
||
; in res attrib anyway, and won't help for ROM-based drivers. .
|
||
; .). Now do a ReservMem before allocating new DCEs which should
|
||
; help here. Open gets special IOPermission field for OpenDeskAcc
|
||
; Opens and now doesn't pass on to file system for these. Open
|
||
; checks non-deskmgr Opens for a period prefix and goes
|
||
; immediately to File System if none; searches currently installed
|
||
; drivers first before trying Resources and won't blast a
|
||
; currently opened driver. Close fail leaves driver looking open.
|
||
; Open fail leaves driver looking closed. Open, Close, Read,
|
||
; Write, Control, and Status now return all results in IOResult
|
||
; field as well as in D0. Rather than checking the top request to
|
||
; see if it's immediate (it wouldn't be queued if it was), we just
|
||
; check for no request in queue (this still isn't the whole
|
||
; solution).
|
||
; 2/8/85 LAK Deref DCE ptr after heap compact . . .
|
||
; 1/31/85 LAK Removed fake RTE's for 68010/68020 support.
|
||
; 1/30/85 LAK Added AddDrive routine (used to be in Sony driver).
|
||
; 1/29/85 LAK Put in RAM patches.
|
||
; 9/5/83 LAK Changed IODone to run completion routines at level it is called
|
||
; at.
|
||
; 8/26/83 LAK Changed to save only A1 over completion routine call to speed up
|
||
; async IODone's: completion routine is responsible for preserving
|
||
; A4-A6 and D4-D7 . . . the other registers are saved at the
|
||
; interrupt level.
|
||
; 8/23/83 LAK RWCS now checks for driver open before it will dispatch.
|
||
; 8/17/83 LAK Removed set up of lomem var CurIOTrap; IODone now is smart
|
||
; enough to look at IOTrap and do the RTS itself.
|
||
; 8/15/83 LAK Added FSIODneTbl for initialization.
|
||
; 8/12/83 LAK Open search thru ROM-based drivers only searches thru unit 9 now
|
||
; (last ROM-based driver).
|
||
; 8/8/83 LAK made changes (mostly for code savings) as per 17 July
|
||
; walkthrough.
|
||
; 7/15/83 LAK changed to store trap in IOCmd instead of code.
|
||
; 6/29/83 AJH made ram-based driver ID mapping NOT instead of NEG
|
||
; 6/28/83 AJH fixed bug in string compare for ROM-based driver open
|
||
; 6/26/83 AJH made it save trap in low memory for drivers use
|
||
; 6/24/83 AJH made "noQueue" control calls enter at DoImedIO instead of
|
||
; GoDriver
|
||
; 6/23/83 AJH added "NoQueue" bit to IO traps; made open install drivers
|
||
; simplified DrvrInstall
|
||
; 6/17/83 AJH made it compact heap before locking down opened driver
|
||
; 6/16/83 LAK changed Open and DrvrInstall to use UnitNtryCnt lomem var
|
||
; instead of UnitEntries equate.
|
||
; 6/15/83 AJH made it use symbolic deep shit alert
|
||
; 5/25/83 LAK changed interface to new string compare.
|
||
; 4/27/83 LAK modified changes. added fix for GoDriver out-of-mem error.
|
||
; 4/26/83 AJH optimized IODone path for ROM drivers intercepted status call 1
|
||
; to return DCE handle implemented KillIO
|
||
; 3/10/83 LAK fixed bug in close (wasn't saving registers it restored).
|
||
; 2/22/83 LAK moved CmpString from here to SysUtil; made all routines here
|
||
; preserve regs as per Pascal regsave conventions.
|
||
; 1/23/83 LAK Adapted for new equate files.
|
||
; 1/21/83 LAK modified for new I/O parameter blocks
|
||
; 1/12/83 LAK modified to use OS string compare proc
|
||
; 1/3/83 AJH changed over to new resource manager
|
||
; 12/17/82 LAK integrated with Andy's IOCore (resources!)
|
||
; 12/16/82 LAK when calling completion routine, param blk ptr is now passed in
|
||
; A0, D0 result code is tested. changed IOResult to be positive
|
||
; when "in progress", negative or zero when done.
|
||
; 12/2/82 LAK changed IO positioning to be same as file systems; removed
|
||
; references to FileControl, FileStatus (needs corresponding file
|
||
; system changes)
|
||
; 11/15/82 LAK now calls completion routines at IODone
|
||
; 9/5/82 LAK added InstallDriver, RemoveDriver; Included Object Manager;
|
||
; debugged this and previous changes
|
||
; 8/19/82 LAK removed ring buffer stuff and PEEK modified Fetch and STASH to
|
||
; be simpler changed Status, Control to be asynchronous changed to
|
||
; support new Unit Table and Device Control Entry formats position
|
||
; parameters for read and write calls are now evaluated when the
|
||
; prime routine is called (instead of when the command is
|
||
; received) made string-compare case insensitive (pretty much)
|
||
; 11/16/81 AJH integrated file system
|
||
; 11/15/81 AJH made READ and WRITE look at async bit
|
||
; 11/2/81 AJH moved UNITABLE to heap
|
||
; 10/20/81 bmw fetch advances pointer after getting byte
|
||
; 10/15/81 bmw random bugfixes
|
||
; 10/14/81 AJH changed fetch,stash,read,write,aread,awrite to for the new way
|
||
; of doing things; added IODONE
|
||
; 10/11/81 bmw separate synchronous from asnychronous symbolic offsets,
|
||
; doasynch, dowasynch bugfix; control, status bugfix, consolidated
|
||
; dispatching to driver routines
|
||
; 10/5/81 bmw add deferred completion routines
|
||
; 10/2/81 bmw close bugfix
|
||
; 10/1/81 bmw make control, status give user's a0 to driver
|
||
; 9/29/81 bmw make goprime clear d0
|
||
; 9/18/81 bmw fetch bugfix
|
||
; 9/15/81 AJH Changed structure of FETCH/NEXTFETCH
|
||
; 7/17/81 AJH Added asynchronous I/O stuff
|
||
;
|
||
|
||
BLANKS ON
|
||
STRING ASIS
|
||
|
||
LOAD 'StandardEqu.d'
|
||
INCLUDE 'HardwarePrivateEqu.a'
|
||
INCLUDE 'UniversalEqu.a'
|
||
|
||
INCLUDE 'Slots.a'
|
||
INCLUDE 'ROMEqu.a'
|
||
|
||
|
||
IOCore PROC EXPORT
|
||
|
||
EXPORT Read,Write
|
||
EXPORT ControlTrap,StatusTrap,Open,Close,KillIOTrap
|
||
EXPORT Fetch,Stash,IODone,FSIODneTbl
|
||
EXPORT DrvrInstall,DrvrRemove
|
||
EXPORT AddDriveTrap
|
||
EXPORT vGoDriver,vWaitUntil,vSyncWait
|
||
|
||
IMPORT EnqueueTrap,DequeueTrap,InitQueue
|
||
IMPORT FileRead,FileWrite
|
||
IMPORT FileOpen,FileClose
|
||
|
||
FSIODneTbl
|
||
DC.W Fetch-FSIODneTbl
|
||
DC.W Stash-FSIODneTbl
|
||
DC.W IODone-FSIODneTbl
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: Fetch
|
||
; Arguments: A1 (input) -- pointer to device control entry
|
||
; D0 (output) -- requested byte- bit 15 = 1 if last byte
|
||
; all other registers are preserved
|
||
;
|
||
; Function: Used to fetch the next byte from user buffer for
|
||
; output I/O requests. The last character is returned with
|
||
; bit 15 set; the driver should output the last byte
|
||
; and then jump to IODone.
|
||
;______________________________________________________________________
|
||
|
||
Fetch BCLR #15,D0 ; set Fetch flag
|
||
|
||
FetchStash MOVEM.L D1/A2-A3,-(SP) ; save relevant registers
|
||
MOVE.L DCtlQHead(A1),D1 ; get pointer to request
|
||
BEQ.S IOCoreErr ; trap if there is no request
|
||
MOVE.L D1,A3
|
||
MOVE.L IONumDone(A3),D1 ; get buffer pointer
|
||
MOVE.L IOBuffer(A3),A2 ; get pointer to buffer
|
||
BCLR #15,D0 ; fetch or stash?
|
||
BNE.S StashOne ; branch for Stash
|
||
|
||
MOVE.B 0(A2,D1.L),D0 ; fetch it!
|
||
BRA.S FinishFS
|
||
|
||
StashOne MOVE.B D0,0(A2,D1.L) ; stash it!
|
||
|
||
FinishFS ADDQ.L #1,D1 ; compute new count
|
||
MOVE.L D1,IONumDone(A3) ; update the count
|
||
CMP.L IOByteCount(A3),D1 ; if this doesn't finish the request
|
||
BLT.S FSDone ; then continue on
|
||
BSET #15,D0 ; hi bit on indicates no more
|
||
|
||
FSDone
|
||
;;;; TST.W D0 ; set condition codes <05Jun85>
|
||
EXT.L D0 ; make it long and test <05Jun85>
|
||
|
||
MOVEM.L (SP)+,D1/A2-A3
|
||
RTS
|
||
|
||
IOCoreErr MOVEQ #DSIOCoreErr,D0 ; deep shit IOCore error
|
||
_SysError ; invoke deep shit
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: Stash
|
||
; Arguments: A1 (input) -- pointer to device control entry
|
||
; D0 (input) -- byte to stash
|
||
; D0 (output) -- bit 15 = 1 if I/O request finished
|
||
; all other registers are preserved
|
||
;
|
||
; Function: Used to store the next input byte into user buffer (for
|
||
; input I/O requests). The driver should jump to
|
||
; IODone after the last byte.
|
||
;______________________________________________________________________
|
||
|
||
Stash BSET #15,D0 ; set Stash flag
|
||
BRA.S FetchStash ; go share code with Fetch
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: IODone
|
||
; Arguments: A1 (input) -- pointer to device control entry
|
||
; D0 (input) -- I/O result code
|
||
;
|
||
; Function: IODone is a utility routine that is JMPed to by drivers when
|
||
; they have processed all the info in an IO Control Block (for
|
||
; read, write, control, and status calls).
|
||
; Condition codes are preserved (why?).
|
||
;
|
||
; Modification History:
|
||
; 16 Dec 82 LAK When calling completion routine, now passes A0=param blk ptr,
|
||
; D0=result code (CCR set on this)
|
||
;______________________________________________________________________
|
||
|
||
IOOK MOVEQ #0,D0 ; no error
|
||
IODone
|
||
MOVE.W D0,-(SP) ; preserve D0 across IODone <13Jan86>
|
||
|
||
; Since the dce is dereferenced, we
|
||
; must make sure that it is a valid
|
||
; 32-bit address. The only way that
|
||
; we can do so is to assume it is in
|
||
; the lower 16 Megabytes of memory and
|
||
; remove the memory manager crap in the
|
||
; upper byte.
|
||
MOVE.L D0,-(SP) ; save d0 through the trap
|
||
MOVE.L A1,D0 ; modify dce pointer for valid
|
||
; 32 bit address
|
||
_StripAddress ; mask off the top eight bits of d0
|
||
MOVE.L D0,A1 ; restore a1.
|
||
MOVE.L (SP)+,D0 ; restore d0 for routine.
|
||
|
||
BSR.S @1 ; <13Jan86>
|
||
MOVE.W (SP)+,D0 ; <13Jan86>
|
||
RTS ; <13Jan86>
|
||
|
||
@1 MOVE.L DCtlQHead(A1), D1 ; is there a request?
|
||
BEQ.S DeActImed ; br if not
|
||
|
||
MOVE SR,-(SP) ; save interrupt state
|
||
MOVE SR,D1 ; remember SR state
|
||
ORI #HiIntMask,SR ; <24Jul85>
|
||
BSR.S DeActDrvr ; deactivate driver
|
||
|
||
; delete the current request from the queue and post any completion routines
|
||
|
||
BSR.S PostCompletion ; dequeue and post the completion routine
|
||
ORI #HiIntMask,SR ; disable interrupts <24Jul85>
|
||
TST.L DCtlQHead(A1) ; any more pending requests?
|
||
BNE GoIO ; if so, go relaunch the driver <SM7> CSS
|
||
MOVE.W (SP)+, SR ; otherwise, re-enable interrupts and return
|
||
RTS
|
||
|
||
; Routine to mark a driver inactive and then
|
||
; unlock the driver and its DCE if we're allowed to.
|
||
; Nowadays, use mem mgr routines rather than bset/bclr and let <C169>
|
||
; RecoverHandle compute a DCE handle given its pointer. Be careful
|
||
; to preserve D0, an error code, across these calls.
|
||
DeActDrvr BCLR #DrvrActive,DCtlFlags+1(A1) ; mark as inactive
|
||
DeActImed
|
||
BTST #DNeedLock,DCtlFlags(A1) ;does it have to stay locked?
|
||
BNE.S IORTS7 ; exit if so (note that all rom-based
|
||
; drivers have this bit set . . .)
|
||
|
||
MOVEA.L DCtlDriver(A1),A0 ; get handle to the driver
|
||
|
||
MOVE.L D0,-(SP) ; save result code across traps <C169>
|
||
_HUnlock ; <C169>
|
||
MOVEA.L A1,A0 ; A0 <- DCE ptr <C169>
|
||
_RecoverHandle ,Sys ; A0 <- handle <v1.5>
|
||
_HUnlock ; <C169>
|
||
MOVE.L (SP)+,D0 ; restore result code <C169>
|
||
|
||
IORTS7 RTS
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Routine: PostCompletion
|
||
; Arguments: A1 (input) -- pointer to Device Control Entry for driver
|
||
; D0 (input) -- error code to post in IOResult
|
||
; D1 (input) -- interrupt state to call completion routine at
|
||
; A1 is preserved; D0-D3, A0, A2-A3 may be trashed by
|
||
; completion routine.
|
||
; Called By: IODone, KillIO
|
||
;
|
||
; Function: PostCompletion dequeues the current request, posts the
|
||
; result code as specified by A0 and runs the completion
|
||
; routine if neccessary. It should be called with
|
||
; interrupts disabled. D0 contains the error code.
|
||
;
|
||
;______________________________________________________________________
|
||
|
||
PostCompletion ; <13> rb
|
||
|
||
MOVE.L DCtlQHead(A1),A0 ; A0 -> current request
|
||
CMP.W #IOQType,QType(A0) ; it better be an I/O queue element
|
||
BNE.S IOCoreErr ; or else die
|
||
|
||
MOVE.L QLink(A0),DCtlQHead(A1) ; get next request, if any
|
||
BNE.S @0 ; branch if queue not empty
|
||
CLR.L DCtlQTail(A1) ; clear tail ptr, too
|
||
|
||
@0 MOVE D1,SR ; restore interrupt state except for KillIO
|
||
MOVE.W D0,IOResult(A0) ; post error code
|
||
BLE.S @1 ; make sure it's negative or zero
|
||
CLR.W IOResult(A0) ; all positive values are cool <02May85>
|
||
|
||
@1 MOVE.L IOCompletion(A0),D1 ; is there a completion routine?
|
||
BEQ.S @2 ; skip if there's not
|
||
|
||
MOVE.L A1,-(SP) ; save A1 over call
|
||
MOVE.L D1,A1 ; get the completion routine address
|
||
|
||
;;;; TST.W D0 ; test result code <05Jun85>
|
||
EXT.L D0 ; make it long and test <05Jun85>
|
||
|
||
JSR (A1) ; call it
|
||
MOVE.L (SP)+,A1 ; restore A1
|
||
@2
|
||
RTS
|
||
;______________________________________________________________________
|
||
;
|
||
; Routine: DoAsyncIO
|
||
; Arguments: A0 (input) -- pointer to I/O command parameter block
|
||
; A1 (input) -- pointer to Device Control Entry for driver
|
||
; D0 (output) -- error code
|
||
; pascal regsave conventions are observed
|
||
; Called By: IORWCS (br's here for async, bsr's for sync)
|
||
;
|
||
; Function: This core routine allows asynchronous calls to drivers.
|
||
; It does this by building an I/O queue element (in the
|
||
; caller's memory space), queueing it up and calling
|
||
; the driver.
|
||
;
|
||
;______________________________________________________________________
|
||
|
||
DoAsyncIO MOVE.L A1,D1 ; save device control entry pointer
|
||
LEA DCtlQueue(A1),A1 ; get pointer to driver's queue
|
||
|
||
MOVE SR,-(SP) ; only allow level 3
|
||
ORI #HiIntMask,SR ; interrupts for debugging <24Jul85>
|
||
|
||
JSR EnqueueTrap ; queue up the request
|
||
MOVE.L D1,A1 ; restore A1
|
||
|
||
GoIO BSET #DrvrActive,DCtlFlags+1(A1) ; is it active?
|
||
BEQ.S @1 ; if not, just call it
|
||
|
||
; The driver is busy so we're done for now. We'll get to it when the driver
|
||
; calls the IODone routine.
|
||
|
||
MOVEQ #0,D0 ; no errors
|
||
MOVE.W (SP)+, SR ; re-enable interrupts and return
|
||
RTS
|
||
|
||
; The driver was inactive so set things up and kick it off
|
||
|
||
@1 MOVE (SP)+,SR ; restore interrupt state
|
||
MOVE.L DCtlQHead(A1),A0 ; get pointer to request
|
||
DoImedIO
|
||
MOVEQ #DrvrCtl,D1 ; control routine offset within driver
|
||
CMP.B #ACtlCmd,IOTrap+1(A0) ; is it control, tho?
|
||
BEQ.S GoDriver ; do it, if so
|
||
MOVEQ #DrvrStatus,D1 ; status routine offset within driver
|
||
CMP.B #AStsCmd,IOTrap+1(A0) ; is it status, tho?
|
||
BEQ.S GoDriver
|
||
|
||
; it must be read or write . . .
|
||
|
||
TST.L IOByteCount(A0) ; if nothing to do, don't bother
|
||
BEQ.S IOOK ; and just say its done (IO drivers
|
||
; usually assume a non-zero count)
|
||
MOVE.W IOPosMode(A0),D0 ; get positioning mode
|
||
MOVE.L IOPosOffset(A0),D1 ; get position offset
|
||
ROXR.B #2,D0 ; get pos bits into carry, sign
|
||
BPL.S @2 ; 0,2 do nothing
|
||
BCC.S @1 ; 1 is absolute (rel to beginning)
|
||
|
||
ADD.L DCtlPosition(A1),D1 ; mode 3: relative to current position
|
||
@1 MOVE.L D1,DCtlPosition(A1) ; mode 1: relative to beginning
|
||
; posmode0 and 2 are no-ops
|
||
|
||
@2 MOVEQ #DrvrPrime,D1 ; we want to call the prime routine
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Routine: GoDriver
|
||
; Arguments: A1 (input) -- pointer to Device Control Entry for driver
|
||
; D1 (input) -- offset to appropriate driver routine
|
||
; D3-D7, A1-A6 are preserved over driver call.
|
||
; Called By: GoIO(IODone), DoImedIO(IORWCS), Open, Close, KillIO,
|
||
; DoAsyncIO(Read,Write,Control,Status)
|
||
;
|
||
; Function: General method to call a driver's routine. calls the
|
||
; driver's routine with D0 clear and A0 and A1 containing
|
||
; what they contained on entry...
|
||
;
|
||
;______________________________________________________________________
|
||
|
||
GoDriver MOVE.L jGoDriver,-(SP) ; get jump vector <C805>
|
||
RTS ; and go to it <C805>
|
||
|
||
vGoDriver MOVE.L DCtlDriver(A1),D0 ; if the unit doesn't have a driver, <C805>
|
||
BNE.S @0 ; then complain
|
||
|
||
; If the entry in the unit table is nil, the requested driver doesn't exist.
|
||
; Flag the error and return to user.
|
||
|
||
MOVEQ #UnitEmptyErr,D0
|
||
MOVE.W D0,IOResult(A0) ; post the error
|
||
RTS
|
||
|
||
@0 MOVEM.L D3-D7/A1-A6,-(SP) ; save regs over driver call
|
||
MOVE.L D0,A2 ; get the handle or ptr
|
||
BTST #DRAMBased,DCtlFlags+1(A1) ; ptr or handle?
|
||
BEQ.S @2 ; if ROMBased, we have it
|
||
|
||
; Slow but 32-bit friendly way is to set A3 to the handle of data at A1 after locking
|
||
; that data. A0 is preserved.
|
||
MOVEA.L A0,A3 ; save A0 across lock of handle of A1 <C169>
|
||
MOVEA.L A1,A0 ; A1 = ptr to handle data to lock <C169>
|
||
_RecoverHandle ,Sys ; A0 <- driver handle <C169>
|
||
_HLock ; <v1.6>
|
||
EXG A0,A3 ; A3 <- (locked) handle; A0 <- old value <C169>
|
||
|
||
TST.L (A2) ; driver been purged?
|
||
BNE.S @1 ; br if not
|
||
MOVE.L A2,-(SP) ; push driver handle
|
||
_LoadResource ; load the driver (preserves A0 A1 D1)
|
||
MOVE.W ResErr,D0 ; did we get it?
|
||
BNE.S GoError ; if not, we're in trouble
|
||
@1
|
||
EXG A0,A2 ; save A0 across lock <C169>
|
||
_HLock ; lock driver before calling <C169>
|
||
EXG A0,A2 ; restore A0, A2 to original vals <C169>
|
||
|
||
;<put @2 here if ROM-res has handle also . . . maybe just use need's lock?>
|
||
|
||
; Slow but 32-bit friendly way to deref and strip a handle <C169>
|
||
MOVE.L (A2),D0 ; D0 <- driver ptr <C169>
|
||
_StripAddress ; <C169>
|
||
MOVEA.L D0,A2 ; replacing handle with cool ptr <C169>
|
||
|
||
@2 MOVE.W 0(A2,D1.W),D1 ; to the desired routine
|
||
MOVEQ #0,D0 ; assume no errors
|
||
JSR 0(A2,D1.W) ; call it with A0=param ptr, A1=DCE ptr
|
||
BRA.S RegExit ; and return, successful
|
||
|
||
; The loadResource wasn't successful, so set IOResult to the error code
|
||
; and return to user.
|
||
|
||
GoError MOVE.W D0,IOResult(A0) ; post the error
|
||
|
||
RegExit
|
||
EXT.L D0 ; extend error code from ResErr or desired routine <05Jun85>
|
||
|
||
MOVEM.L (SP)+,D3-D7/A1-A6 ; restore regs
|
||
RTS ;
|
||
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Routine: MapUnit
|
||
; Arguments: D2 (input) -- unit RefNum
|
||
; A1 (output) -- pointer to Device Control Entry
|
||
; A2 (output) -- handle of DCE memory block
|
||
; Called By: Open, Close, IORWCS, Status, KillIO
|
||
;
|
||
; Function: Maps an I/O RefNum to a Device Control Entry pointer; only
|
||
; I/O driver RefNums are mapped. Z-bit = 1 if purged.
|
||
;______________________________________________________________________
|
||
|
||
|
||
MapUnit NOT.W D2 ; bitwise complement to get unitnum
|
||
BMI.S BadUnit
|
||
CMP.W UnitNtryCnt,D2 ; is it in range?
|
||
BGE.S BadUnit ; skip if its not
|
||
|
||
ASL.W #2,D2 ; multiply by four
|
||
MOVE.L UTableBase,A1 ; get address of unit table
|
||
MOVE.L 0(A1,D2.W),D2 ; add in the offset
|
||
BEQ.S BadUnit ; branch if there is no driver installed
|
||
|
||
MOVE.L D2,A2 ; DCE handle
|
||
MOVE.L (A2),D2 ; dereference handle
|
||
BEQ.S IOCoreErr ; syserror if purged (DCE should never be)
|
||
MOVE.L D2,A1 ; pointer to Device Control Entry
|
||
RTS
|
||
|
||
BadUnit MOVE.L D5, A0 ; restore parameter blk ptr
|
||
MOVEM.L (SP)+,D0/D3-D5/A2-A4 ; restore regs and pop return address <C133/29Aug86>
|
||
; into D0!!
|
||
MOVEQ #BadUnitErr,D0 ; flag the error
|
||
MOVE.W D0, IOResult(A0) ; also return in IOResult
|
||
RTS
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Routine: IsSlotDrvr
|
||
; Arguments: D5 (input) -- pointer to io parameter block.
|
||
; CCR (output) -- zero flag set if for a slot device, clear otherwise.
|
||
; Called By: Open
|
||
; Function: Test to see if the call is for a slot device or a motherboard device.
|
||
; Destroys: A4.
|
||
;______________________________________________________________________
|
||
|
||
IsSlotDrvr MOVEM.L D0,-(SP) ; Save D0
|
||
|
||
MOVE.L D5,A4 ; A4 <- pointer to io parameter block.
|
||
BTST.B #HFSBit-8,IOTrap(A4) ; Is this an extended parameter block call?
|
||
BEQ @NotSlot ; br if not.
|
||
|
||
BTST #fMulti,ioFlags+1(A4) ; does this extended parameter block use ioSEBlkPtr? <C620>
|
||
BNE.S @IsSlot ; br if does (must be a slot device if it is using ioSEBlkPtr).
|
||
|
||
; Test both slot and sRsrc id for zero. If both zero, then assume this is
|
||
; not a slot driver. This fixes a problem with opening the .ENET driver on
|
||
; both slot zero and in the system disk.
|
||
|
||
@10 TST.W ioSlot(A4) ; ioSlot is valid since fMulti flag is clear. If slot = 0 then <12> rb
|
||
BEQ @NotSlot ; not a slot driver.
|
||
|
||
|
||
; Set the Status.
|
||
@IsSlot MOVEQ #0,D0 ; Is a slot driver (Set CCR).
|
||
BRA.S @End
|
||
|
||
@NotSlot MOVEQ #-1,D0 ; not a slot driver (Set CCR).
|
||
|
||
|
||
; Done.
|
||
@End MOVEM.L (SP)+,D0 ; Restore D0.
|
||
RTS
|
||
|
||
|
||
;______________________________________________________________________ <C600>
|
||
; <C600>
|
||
; Routine: SetUpspBlk <C600>
|
||
; Arguments: D5 (input) -- pointer to io parameter block. <C600>
|
||
; A4 (input) -- pointer to SDM parameter block. <C600>
|
||
; A0 (output) -- pointer to io parameter block. <C600>
|
||
; Called By: Open <C600>
|
||
; Function: Set up the spBlock parameters. <C600>
|
||
; Destroys: D0 <C600>
|
||
;______________________________________________________________________ <C600>
|
||
WITH spBlock,seBlock
|
||
|
||
SetUpspBlk MOVE.L D5,A0 ; restore the io parameter block ptr.
|
||
|
||
MOVE.L ioFileName(A0),spIOFileName(A4)
|
||
|
||
MOVE.W ioFlags(A0),D0 ; does this extended parameter block use ioSEBlkPtr?<C600>
|
||
BTST.L #fMulti,D0
|
||
BEQ.S @10 ; br if not.
|
||
|
||
MOVE.L A0,D0 ; save the io parameter block ptr.
|
||
MOVE.L ioSEBlkPtr(A0),A0 ; A0 <- pointer to the seBlock.
|
||
MOVE.L A0,spsExecPBlk(A4) ; Set spsExecPBlk.
|
||
MOVE.B seSlot(A0),spSlot(A4) ; The slot.
|
||
MOVE.B sesRsrcId(A0),spId(A4) ; The sResource Id.
|
||
MOVE.B seDevice(A0),spExtDev(A4) ; The External device.
|
||
MOVE.L D0,A0 ; restore the io parameter block ptr.
|
||
BRA.S @End ;
|
||
|
||
@10 MOVE.B ioSlot(A0),spSlot(A4) ; The slot.
|
||
MOVE.B ioId(A0),spId(A4) ; The sResource Id.
|
||
CLR.B spExtDev(A4) ; Default to External device of 0.
|
||
|
||
|
||
; Done.
|
||
@End RTS
|
||
ENDWITH
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: Open
|
||
; Arguments: A0 (input) -- pointer to Open parameter block
|
||
; D0 (output) -- error code
|
||
; D1 (input) -- OS Call trap word
|
||
;
|
||
; Function: We look up the input filename in the object manager data
|
||
; structure (for ram-based drivers) and indirect thru the
|
||
; Unit Table (for rom-based drivers); if an I/O driver is
|
||
; installed, we make a synchronous call to that I/O driver,
|
||
; and return the proper unit number as the refnum;
|
||
; otherwise we let the file system take care of it.
|
||
;
|
||
;______________________________________________________________________
|
||
|
||
; It wasn't found in the device table so let the file system deal with it
|
||
|
||
ToFSOpen MOVE.L D5,A0 ; restore parameter block pointer
|
||
MOVE.W IOTrap(A0),D1 ; restore D1
|
||
MOVEM.L (SP)+,D3-D5/A2-A4 ; restore regs <C133/29Aug86>
|
||
CMP.B #$40,IOPermssn(A0) ; is it from OpenDeskAcc?? <01Nov85>
|
||
BEQ.S @1 ; br if so (won't be in the file system . . .)
|
||
|
||
tst.w FSFCBLen ; Do we have a file system? <PWD/21Mar90>
|
||
bmi.s @1 ; br if not <PWD/21Mar90>
|
||
|
||
JMP FileOpen ; needs D1 and A0 unharmed
|
||
@1 MOVEQ #OpenErr, D0 ; return generic OpenErr to DeskMgr
|
||
BRA OpenExit ; exit, setting IOResult
|
||
|
||
Open MOVEM.L D3-D5/A2-A4,-(SP) ; observe pascal regsave conventions <C133/29Aug86>
|
||
MOVE.L A0,D5 ; save parameter block pointer
|
||
MOVE.W D1,IOTrap(A0) ; and D1
|
||
|
||
MOVE.W IOFileType(A0), D2 ; save for desk acc check
|
||
MOVE.L IOFileName(A0), A0 ; point A0 to input filename for search of installed drivers
|
||
MOVEQ #0,D1 ; clear high bytes
|
||
MOVE.B (A0)+,D1 ; IOFileName length
|
||
|
||
CMP.B #$40,D2 ; is it from OpenDeskAcc?? <01Nov85>
|
||
BEQ NonSlotDrvr ; br if so (acc names should start with a null, but often don't)
|
||
CMP.B #'.',(A0) ; does name start with a period?
|
||
BNE.S ToFSOpen ; must be for the file system if not a
|
||
; deskmgr call or driver name is not prefixed with period
|
||
|
||
|
||
BSR.S IsSlotDrvr ; is this a slot device? <C600>
|
||
BNE NonSlotDrvr ; branch if not. <C600>
|
||
|
||
; ---------+++++++++++ Begin Slot Driver +++++++++++--------- <C133/29Aug86>
|
||
|
||
WITH spBlock, seBlock
|
||
|
||
; Initialize the SDM parameter block
|
||
SlotDrvr SUB.L #spBlockSize,SP ; Allocate parameter block for slot manager
|
||
MOVE.L SP,A4 ; Save pointer to spBlock.
|
||
|
||
BSR SetUpspBlk ; Set up some of the SDM parameters. <C600>
|
||
|
||
|
||
; First search for the driver among those already installed . . .
|
||
MOVE.W UnitNtryCnt, D2 ; number of units to check
|
||
SUB.W #BgnSlotUnit,D2 ; adjust for # of slot unit entries.
|
||
MOVEQ #BgnSlotRef,D4 ; init refnum index
|
||
|
||
MOVE.L UTableBase, A3 ; get address of the unit I/O table
|
||
MOVEQ #BgnSlotUnit,D0 ; adjust to beginning of slot unit entries.
|
||
LSL.L #2,D0
|
||
ADD.L D0,A3 ; A3 <- ptr to unit table, beginning at slot DCE's.
|
||
; REPEAT
|
||
@Repeat MOVE.L (A3)+,D0 ; get next Device Control Entry handle
|
||
BEQ.S @Until ; branch if no entry installed
|
||
MOVE.L D0,A2 ; prepare to de-reference it.
|
||
MOVE.L (A2),D0 ; de-reference it.
|
||
BNE.S @10 ; branch if ok <C750>
|
||
CLR.L -(A3) ; Clear the bad UT entry. <C750>
|
||
BRA.S @Repeat ; Continue at top of loop <C750>
|
||
|
||
@10 MOVE.L D0,A1 ; A1 <- ptr to DCE <C750>
|
||
|
||
MOVE.B dCtlSlot(A1),D0 ; do the slot numbers match?
|
||
CMP.B spSlot(A4),D0
|
||
BNE.S @Until ; if not then continue search.
|
||
|
||
MOVE.B dCtlSlotId(A1),D0 ; do the sResource Id's match?
|
||
CMP.B spId(A4),D0
|
||
BNE.S @Until ; if not then continue search. <C523>
|
||
|
||
MOVE.B dCtlExtDev(A1),D0 ; do the Device Id's match? <C523>
|
||
CMP.B spExtDev(A4),D0 ; <C523><C537>
|
||
BEQ.S DCEFound ; if yes then DCE is found. <C523>
|
||
|
||
@Until SUBQ #1,D4 ; bump refnum index
|
||
SUBQ.W #1,D2 ; next unit table entry
|
||
BGT.S @Repeat ; continue searching.
|
||
; UNTIL (proper DCE is found) OR (unit table entries are exhausted)
|
||
BRA.S LookInRsrc ; not installed, begin looking for driver in resources.
|
||
|
||
; DCE was among the installed slot drivers, but is the driver still installed?
|
||
DCEFound MOVE.L dctlDriver(A1),D0 ; D0 <- handle to the driver
|
||
BEQ.S BadDCE ; if driver handle is nil then there is no driver.
|
||
MOVE.L D0,A1
|
||
MOVE.L (A1),D0 ; D0 <- ptr to the driver
|
||
BNE OldDrvr ; if driver ptr is not nil then driver is already here, goto DrvrLock.
|
||
|
||
BadDCE MOVE.L A2,A0 ; if no driver, then purge the DCE, and reload and install the driver.
|
||
_DisposPtr ; dispose of DCE
|
||
MOVE.L #0,-(A3) ; clear unit table entry
|
||
|
||
; It wasn't among the installed slot drivers, so check resources . . .
|
||
LookInRsrc SUBQ #4,SP ; make room for result
|
||
MOVE.L #'DRVR',-(SP) ; push resource class DRVR
|
||
MOVE.L spIOFileName(A4),-(SP) ; push name pointer
|
||
MOVE.W #MapTrue,ROMMapInsert ; in case it's in sys ROM <C632/14Jan87> DAF
|
||
_GetNamedResource ; search resource files first (blows A0, D1??)
|
||
MOVE.L (SP)+,D3 ; did it find one? D3 <- handle to driver.
|
||
|
||
; get the slot driver too... ; <C950/08Nov87> DAF
|
||
|
||
LookInSlot MOVE.L A4,A0 ; set A0 for use by the slot manager.
|
||
_sGetDriver ; get the slot driver
|
||
BEQ.S @1 ; continue if no error <C950/08Nov87> DAF
|
||
|
||
TST.L D3 ; was there a resource drvr? <C950/08Nov87> DAF
|
||
BNE.S DetRefNum ; yes, only from disk, so continue <C950/08Nov87> DAF
|
||
BRA DrvrBad ; branch if driver not found <C950/08Nov87> DAF
|
||
|
||
@1 MOVE.L spResult(A0),A3 ; get the handle to the driver <C950/08Nov87> DAF
|
||
MOVE.L (A3),A1 ; get the pointer to the driver <C950/08Nov87> DAF
|
||
CLR.L D0 ; for upcoming add <C950/08Nov87> DAF
|
||
MOVE.B drvrName(A1),D0 ; get the driver name length <C950/08Nov87> DAF
|
||
ADDQ #2,D0 ; Adjust offset to version field <C950/08Nov87> DAF
|
||
BCLR #0,D0 ; Adjust to word alignment <C950/08Nov87> DAF
|
||
MOVE.W drvrName(A1,D0.W),D0 ; Get the sDriver version number <C950/08Nov87> DAF
|
||
|
||
;
|
||
; compare DRVR resource version with sDrvr version, being careful to test if the
|
||
; drivers were really present. Iff the DRVR version is greater, use it, else
|
||
; use the slot drvr, or finally, no driver available, return error <C950/08Nov87> DAF
|
||
;
|
||
|
||
TST.L D3 ; is there a resource driver? <C950/08Nov87> DAF
|
||
BEQ.S @UseSlot ; if no system driver, use sDrvr <C950/08Nov87> DAF
|
||
MOVE.L D3,A0 ; get handle in an A-reg <C950/08Nov87> DAF
|
||
MOVE.L (A0),A0 ; get pointer <C950/08Nov87> DAF
|
||
CLR.L D2 ; for upcoming add <C950/08Nov87> DAF
|
||
MOVE.B drvrName(A0),D2 ; get the driver name length <C950/08Nov87> DAF
|
||
ADDQ #2,D2 ; Adjust offset to version field. <C950/08Nov87> DAF
|
||
BCLR #0,D2 ; Adjust alignment. <C950/08Nov87> DAF
|
||
CMP.W drvrName(A0,D2.W),D0 ; Compare versions with sDrvr <C950/08Nov87> DAF
|
||
BGE.S @UseSlot ; if sDrvr ≥ drvr, then use sDrvr <C950/08Nov87> DAF
|
||
|
||
MOVE.L A3,A0 ; get rid of slot driver <C950/08Nov87> DAF
|
||
_DisposHandle ; <C950/08Nov87> DAF
|
||
MOVE.L D3,-(SP) ; we need to detach the resource! <C950/08Nov87> DAF
|
||
_DetachResource ; <C950/08Nov87> DAF
|
||
BRA.S DetRefNum
|
||
|
||
@UseSlot
|
||
MOVE.L D3,-(SP) ; push the resource handle <C950/08Nov87> DAF
|
||
_ReleaseResource ; we're using the sDrvr, so dump the system drvr <C950/08Nov87> DAF
|
||
MOVE.L A3,D3 ; slotDrvr handl in A3 <C950/08Nov87> DAF
|
||
|
||
; Driver was loaded from resource file or slot, now determine the reference number.
|
||
; Reference num will be related to the first available entry in the unit table.
|
||
DetRefNum
|
||
; <C334>
|
||
MOVE.L D0,-(SP) ; save d0 on the stack
|
||
MOVE.L D3,D0 ; move address to strip
|
||
_StripAddress ; yank off the top byte...extraneous memory manager stuff.
|
||
MOVE.L D0,D3 ; restore to proper register
|
||
MOVE.L (SP)+,D0 ; restore d0
|
||
|
||
@10 MOVEQ #BgnSlotRef,D4 ; init refnum index
|
||
MOVE.W UnitNtryCnt,D2 ; number of units to check
|
||
SUB.W #BgnSlotUnit,D2 ; adjust for # of slot unit entries.
|
||
|
||
MOVE.L UTableBase, A3 ; get address of the unit I/O table
|
||
MOVEQ #BgnSlotUnit,D0 ; adjust to beginning of slot unit entries.
|
||
LSL.L #2,D0
|
||
ADD.L D0,A3 ; A3 <- ptr to unit table, beginning at slot DCE's.
|
||
; REPEAT
|
||
@Repeat TST.L (A3)+ ; Test next Device Control Entry handle <C750>
|
||
BEQ DrvrSet ; branch if empty unit entry is found, D4 = RefNum
|
||
SUBQ #1,D4 ; bump refnum index
|
||
SUBQ.W #1,D2 ; next unit table entry
|
||
@Until BGT.S @Repeat ; UNTIL (empty unit entry is found) OR (end of unit table is reached)
|
||
|
||
CMP.W #MaxUTEntries,UnitNtryCnt ; Check to see if UT is full. <C523>
|
||
BGE.S UTFull ; branch if full. <C523>
|
||
|
||
MOVE.W UnitNtryCnt,D0 ; Get ready to see if UT can grow. <C750>
|
||
ADD.W #4,D0 ; Increase size by 4. (Use an even number so no space is wasted) <C750>
|
||
CMP.W #MaxUTEntries,D0 ; Is it full? <C750>
|
||
BGT.S UTFull ; Branch if full. <C750>
|
||
MOVE.W D0,UnitNtryCnt ; Not full, so let it grow. <C750>
|
||
BRA.S DrvrSet ; We are all set to install the driver. <C750>
|
||
|
||
UTFull MOVE.L D3,A0 ; dispose of the driver, there are no more entries available in theunit table.
|
||
_DisposHandle
|
||
MOVE.W #UnitTblFullErr,D0 ; Error, No more unit entries are available.
|
||
ADD.L #spBlockSize,SP ; deallocate spBlock. <C620>
|
||
BRA OpenEnd ; <C620>
|
||
|
||
DrvrBad ADD.L #spBlockSize,SP ; deallocate spBlock
|
||
BRA ToFSOpen ; go to FSOpen. <C787>
|
||
|
||
DrvrSet ADD.L #spBlockSize,SP ; deallocate spBlock
|
||
BRA InstallDrvr
|
||
|
||
OldDrvr ADD.L #spBlockSize,SP ; deallocate spBlock
|
||
BRA DrvrLock ; if driver ptr is not nil then driver is already here, goto DrvrLock.
|
||
|
||
ENDWITH
|
||
|
||
|
||
; ---------+++++++++++ Begin Non-Slot Driver +++++++++++---------
|
||
|
||
; First search for the driver among those already installed . . .
|
||
|
||
NonSlotDrvr MOVE.L UTableBase, A3 ; get address of the unit I/O table
|
||
MOVE.W UnitNtryCnt, D2 ; number of units to check
|
||
MOVEQ #-1,D4 ; init refnum index
|
||
|
||
CkInstLoop
|
||
MOVE.L (A3)+,D0 ; get next Device Control Entry handle
|
||
BEQ.S NextEntry ; branch if no entry installed
|
||
MOVE.L D0,A2 ; DCE handle
|
||
MOVE.L (A2),D0 ; dereference handle
|
||
BEQ.S NextEntry ; branch if null
|
||
MOVE.L D0,A1 ; A1 -> Device Control Entry
|
||
|
||
BTST #DRAMBased,DCtlFlags+1(A1) ; ROM-based?
|
||
MOVE.L DCtlDriver(A1), A1 ; driver ptr/handle
|
||
BEQ.S @1 ; br if ROM-based (A1 is a pointer)
|
||
MOVE.L A1, D0 ; be clean and check for 0 handle
|
||
BEQ.S NextEntry ; skip if so
|
||
MOVE.L (A1), A1 ; deref handle
|
||
@1 MOVE.L A1, D0 ; is driver ptr nil?
|
||
BEQ.S NextEntry ; br if so
|
||
|
||
LEA DrvrName(A1),A1 ; point A1 to driver name
|
||
MOVE.L D1, D0 ; A0 points to input filename, D1 is name length
|
||
SWAP D0
|
||
MOVE.B (A1)+, D0 ; string 2 length
|
||
CMP.B D0, D1 ; are lengths the same?
|
||
BNE.S NextEntry ; br if not (names shouldn't match if not)
|
||
_CmpString
|
||
BEQ DrvrLock ; branch if they matched (D4=refnum,
|
||
; A2=DCE handle, D5=IO param blk ptr)
|
||
NextEntry SUBQ #1,D4 ; bump refnum index
|
||
SUBQ.W #1,D2 ; next unit table entry
|
||
BGT.S CkInstLoop ; continue searching through all drivers
|
||
|
||
; It wasn't among the installed drivers/desk accessories, so go check resources . . .
|
||
|
||
SUBQ #4,SP ; make room for result
|
||
MOVE.L #'DRVR',-(SP) ; push resource class DRVR
|
||
MOVE.L D5,A0 ; restore parameter block pointer
|
||
MOVE.L IOFileName(A0),-(SP) ; push name pointer
|
||
MOVE.W #MapTrue,ROMMapInsert ; in case it's in ROM . . . <10Jul85>
|
||
_GetNamedResource ; search resource manager first (blows A0, D1??)
|
||
MOVE.L (SP)+,D3 ; did it find one?
|
||
BNE.S gotDrvr ; br if so <04Oct85>
|
||
|
||
MOVE.W ResErr, D0 ; pass on the error code <04Oct85>
|
||
BEQ.S ToFSOpen ; br if ResNotFound . . . <04Oct85>
|
||
CMP.W #ResNotFound,D0 ; <01Nov85>
|
||
BEQ.S ToFSOpen ; br if ResNotFound . . . <01Nov85>
|
||
BRA OpenEnd ; exit open <04Oct85>
|
||
|
||
; Figure out the driver's ID by using GetResInfo. D3 has driver handle . . .
|
||
|
||
gotDrvr CLR.W -(SP) ; room for ID
|
||
MOVE.L SP,D0 ; save ptr
|
||
MOVE.L D3,-(SP) ; push driver handle
|
||
MOVE.L D0,-(SP) ; ptr to place to stick id
|
||
CLR.L -(SP) ; we don't want the type
|
||
CLR.L -(SP) ; we don't want the name
|
||
MOVE.W #MapTrue,ROMMapInsert ; in case it's in ROM . . . <10Jul85>
|
||
_GetResInfo
|
||
MOVE.W (SP)+,D4 ; get the ID
|
||
NOT.W D4 ; map into refNumber
|
||
|
||
; make sure the driver is installed
|
||
|
||
MOVE.W D4,D0 ; put refNum in D0
|
||
BSR MpUnitNum ; is it installed?
|
||
BMI OpenEnd ; if bad, give up
|
||
BNE.S DInstalled ; if so, we're cool, continue
|
||
|
||
InstallDrvr MOVE.W D4,D0 ; put refNum in D0
|
||
MOVE.L D3, A0 ; A0 <- handle to driver
|
||
MOVE.L (A0), A0 ; dereference driver handle
|
||
BTST #DNeedLock,(A0) ; needs lock?
|
||
BEQ.S @0 ; br if not
|
||
DC.W $A43D ; _DrvrInstall, LOCK
|
||
BRA.S @1
|
||
@0 _DrvrInstall ; install it
|
||
@1 BNE OpenEnd ; if bad, give up <<unlock driver here???>>
|
||
|
||
; Driver is installed, continue.
|
||
|
||
DInstalled MOVE D4,D2 ; make sure D2 has the refNum
|
||
BSR MapUnit ; map it: DCE pointer->A1, DCE handle->A2
|
||
|
||
BSET #DOpened,DCtlFlags+1(A1) ; already opened??
|
||
BNE DrvrLock ; br if so (assume it's the same driver??)
|
||
|
||
;?? maybe we should check the driver handle to see if it is the same driver:
|
||
;
|
||
; SAME OPENED
|
||
;
|
||
; yes yes - return ok, don't call driver (unless it's a desk acc)
|
||
; yes no - call driver open
|
||
; no yes - close and remove old driver?? error??
|
||
; no no - remove old driver??
|
||
|
||
MOVEQ #$40, D0 ; assume DCtlFlags=$40 (DRamBased)
|
||
MOVE.L D3, DCtlDriver(A1) ; handle to driver code -> DCE
|
||
MOVE.L D3, A0 ; get handle in A-reg
|
||
MOVE.L (A0), D0 ; dereference driver handle
|
||
_StripAddress ; modify address to be correct
|
||
MOVE.L D0,D3 ; place in original location
|
||
MOVE.L ROMBase,D0 ; get start address of ROM <v1.3>
|
||
_StripAddress ; clean address if necessary <v1.3>
|
||
CMP.L D0, D3 ; in RAM? <<assumes ROM is above RAM>> <v1.3>
|
||
BLO.S @3 ; br if so (make Jerome happy) <C54>
|
||
|
||
MOVE.L D3, DCtlDriver(A1) ; keep ptr to driver instead for ROM-based (MAY CHANGE)
|
||
MOVEQ #0, D0 ; zero DRamBased
|
||
BRA.S @5 ; branch <v1.3>
|
||
|
||
@3 MOVEQ #$40, D0 ; DCtlFlags=$40 (DRamBased)
|
||
@5 MOVE.L D3,A0 ; driver ptr
|
||
MOVE.W (A0)+,DCtlFlags(A1) ; flags from driver -> DCE
|
||
MOVE.B D0,DCtlFlags+1(A1) ; DrvrActive and DOpened = 0
|
||
MOVE.L (A0)+,DCtlDelay(A1) ; copy DrvrDelay,DrvrEMask
|
||
MOVE.W (A0)+,DCtlMenu(A1) ; and DrvrMenu
|
||
|
||
WITH spBlock
|
||
|
||
; Check For extended parameter block call.
|
||
BSR.S IsSlotDrvr ; is this a slot device? <C600>
|
||
BNE DrvrLock ; branch if not. <C600>
|
||
|
||
|
||
; Allocate the SDM parameter block
|
||
SUB.L #spBlockSize,SP ; Allocate parameter block for SDM.
|
||
MOVE.L SP,A4 ; A4 <- pointer to spBlock.
|
||
|
||
|
||
; Set DCE extension fields: dCtlSlotId, dCtlSlot and dCtlDevBase.
|
||
BSR SetUpspBlk ; Set up some of the SDM parameters. <C600>
|
||
|
||
MOVE.B spSlot(A4),dCtlSlot(A1) ; set the dCtlSlot field
|
||
MOVE.B spId(A4),dCtlSlotId(A1) ; set the dCtlSlotId field
|
||
MOVE.B spExtDev(A4),dCtlExtDev(A1) ; set the dCtlSlotId field <C523>
|
||
|
||
MOVE.L #0,dCtlDevBase(A1) ; set dCtlDevBase field to nil. <C620>
|
||
MOVE.L A4,A0 ; Determine the pointer to the base of the device. <C620>
|
||
|
||
_sFindDevBase ;Find the base address. <1.9>
|
||
BNE.S DCEExtOk ; dCtlDevBase is nil {not a required field}.<1.9>
|
||
MOVE.L spResult(A0),dCtlDevBase(A1); set dCtlDevBase field <C620>
|
||
|
||
DCEExtOk ADD.L #spBlockSize,SP ; deallocate spBlock
|
||
|
||
|
||
ENDWITH
|
||
|
||
; lock down the DCE and the driver code
|
||
|
||
DrvrLock MOVE.L (A2), A1 ; deref DCE ptr
|
||
BTST #DNeedLock,DCtlFlags(A1) ; need to be locked?
|
||
BEQ.S FoundUnit ; if not, don't lock it
|
||
|
||
MOVE.L DCtlDriver(A1),A0 ; get driver code handle
|
||
BTST #DRamBased, DCtlFlags+1(A1)
|
||
BEQ.S @1 ; skip driver lock if not RAM-based
|
||
|
||
_HLock ; lock RAM-based driver <C169>
|
||
@1
|
||
MOVEA.L A2,A0 ; A0 <- DCE handle <C169>
|
||
_HLock ; lock DCE regardless of driver <C169>
|
||
; we found the unit so call it
|
||
; A1 = DCE pointer and D4 = refnum
|
||
|
||
FoundUnit MOVE.L D5,A0 ; restore parameter block pointer
|
||
MOVE.W D4,IORefNum(A0) ; return the refnum
|
||
|
||
MOVEQ #OpenErr,D0 ; assume permissions error
|
||
MOVE.B DCtlFlags(A1),D1 ; get the driver's permission bits
|
||
MOVE D1,D2 ; save it
|
||
OR.B IOPermssn(A0),D1 ; 'or' in open request's permissions
|
||
EOR.B D2,D1 ; if anything changed it's an error
|
||
AND.B #$0003,D1 ; only worry about rd, write
|
||
BNE OpenEnd ; branch if permissions error
|
||
|
||
BSET #DOpened,DCtlFlags+1(A1) ; is it already opened? <04Oct85>
|
||
BEQ.S @1 ; br if not <19Mar85>
|
||
|
||
CMP.B #$40,IOPermssn(A0) ; is it from OpenDeskAcc?? <01Nov85>
|
||
BNE OpenOK ; br if not (call desk accs even if open) <19Mar85>
|
||
|
||
@1 MOVEQ #DrvrOpen,D1 ; open routine offset within driver <19Mar85>
|
||
BSR GoDriver ; call the driver's open routine ??BETTER HAVE A DRIVER??
|
||
; (preserves A1 and A2)
|
||
BPL.S @UpdateSRT ; br if no err (only neg codes are errors) <04Oct85> <C226/10Oct86>
|
||
|
||
MOVE.L D5,A0 ; restore parameter block pointer
|
||
CLR.W IORefNum(A0) ; zero the refnum (failed to open)
|
||
BCLR #DOpened,DCtlFlags+1(A1) ; mark it closed since we failed <04Oct85>
|
||
BRA.S UnLkStuff ; unlock everything since we failed to open
|
||
|
||
@UpdateSRT NOP ; <C226/10Oct86>
|
||
|
||
WITH spBlock
|
||
|
||
; Check For extended parameter block call.
|
||
BSR.S IsSlotDrvr ; is this a slot device? <C600>
|
||
BNE ToUnLkStuff ; branch if not. <C600>
|
||
|
||
|
||
; Allocate the SDM parameter block
|
||
SUB.L #spBlockSize,SP ; Allocate parameter block for SDM.
|
||
MOVE.L SP,A4 ; A4 <- pointer to spBlock.
|
||
|
||
|
||
; Set up the spBlock and update the SRT.
|
||
BSR SetUpspBlk ; Set up some of the SDM parameters. <C600>
|
||
MOVE.W D4,spRefNum(A4) ; Reference number <C542>
|
||
MOVE.W #0,spIOReserved(A4) ; Reserved field, Must be zero now. <C671>
|
||
EXG.L A0,A4 ; Save A0 <C542>
|
||
_sUpdateSRT ; update the Slot Resource Table. <C542>
|
||
EXG.L A4,A0 ; Restore A0 <C542>
|
||
MOVEQ.L #0,D0 ; ignore slot mgr errors <SM3> rb
|
||
|
||
; Done
|
||
ADD.L #spBlockSize,SP ; deallocate spBlock
|
||
|
||
ENDWITH
|
||
|
||
|
||
|
||
ToUnLkStuff BTST #DNeedLock,DCtlFlags(A1) ;does it have to stay locked while open?
|
||
BNE.S OpenEnd ; exit if so
|
||
|
||
UnLkStuff
|
||
; From here to OpenEnd, must unlock 0, 1, or 2 handles. Allowed <C169>
|
||
; to trash A0 but not D0=result code. Use D3 as temp for D0. <C169>
|
||
MOVE.L DCtlDriver(A1),A0 ; get handle to the driver
|
||
BTST #DRamBased, DCtlFlags+1(A1)
|
||
BEQ.S OpenEnd ; don't unlock drivers or DCEs if ROM-based
|
||
|
||
EXG D0,D3 ; preserve error code <C169>
|
||
_HUnlock ; RAM-based drivers <C169>
|
||
EXG D0,D3 ; restore error code <C169>
|
||
|
||
BTST #DNeedLock,DCtlFlags(A1) ; don't unlock the DCE if it's liable to be locked later
|
||
BNE.S OpenEnd ; br if needs lock
|
||
|
||
MOVEA.L A2,A0 ; A0 <- DCE <C169>
|
||
EXG D0,D3 ; preserve error code <C169>
|
||
_HUnlock ; <C169>
|
||
EXG D0,D3 ; restore error code <C169>
|
||
|
||
OpenEnd
|
||
MOVE.L D5,A0 ; restore parameter block pointer
|
||
MOVEM.L (SP)+,D3-D5/A2-A4 ; restore regs <C133/29Aug86>
|
||
|
||
OpenExit MOVE.W D0, IOResult(A0) ; return result here also
|
||
RTS
|
||
|
||
OpenOK MOVEQ #0,D0 ; open was successful (driver already open)
|
||
BRA.S OpenEnd
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: Close
|
||
; Arguments: A0 (input) -- pointer to Close parameter block
|
||
; D1 (input) -- OS Call trap word
|
||
; D0 (output) -- error code
|
||
;
|
||
; Function: If the RefNum is positive, the file system does all the work;
|
||
; otherwise, we make a synchronous call to the IO Driver's
|
||
; Close routine, after waiting for the driver to finish any
|
||
; pending requests. If the driver is a RAM-based driver, its
|
||
; code block is unlocked; the Device Control Entry for the
|
||
; driver is always unlocked.
|
||
;______________________________________________________________________
|
||
|
||
Close MOVE.W IORefNum(A0),D2 ; get the refnum
|
||
BMI.S IOClose ; branch if it's for us
|
||
JMP FileClose ; let the file system handle it
|
||
|
||
IOClose MOVEM.L D3-D5/A2-A4,-(SP) ; observe pascal regsave conventions <C133/29Aug86>
|
||
MOVE.L A0, D5 ; save parameter block ptr
|
||
BSR MapUnit ; get pointer to DCE in A1, handle in A2
|
||
BTST #DOpened,DCtlFlags+1(A1) ; is it open?
|
||
BEQ.S OpenOK ; if not, exit ok
|
||
|
||
WaitUntilDone
|
||
MOVE.L jWaitUntil,-(SP) ; get jump vector <C805>
|
||
RTS ; and jump to it <C805>
|
||
|
||
vWaitUntil BTST #DrvrActive,DCtlFlags+1(A1) ; <C805>
|
||
BNE.S vWaitUntil ; wait until the driver has finished <C805>
|
||
|
||
MOVEQ #DrvrClose,D1 ; close routine offset within driver
|
||
BSR GoDriver ; call the driver's close routine ??BETTER HAVE A DRIVER??
|
||
; (preserves A1 and A2)
|
||
CMP.W #ClosErr,D0 ; failed to close? <04Oct85>
|
||
BEQ.S ToUnLkStuff ; br if close failed (don't mark it closed) <04Oct85>
|
||
|
||
BCLR #DOpened,DCtlFlags+1(A1) ;flag driver as closed <27Jun85>
|
||
|
||
WITH spBlock
|
||
|
||
TST.B DCtlSlot(A1) ; br if not a slot device. <C620>
|
||
BEQ.S @1
|
||
|
||
; Allocate the SDM parameter block
|
||
SUB.L #spBlockSize,SP ; Allocate parameter block for slot manager
|
||
MOVE.L SP,A4 ; A4 <- pointer to spBlock.
|
||
|
||
; Set up the spBlock and update the SRT.
|
||
MOVE.B DCtlSlot(A1),spSlot(A4) ; Slot
|
||
MOVE.B DCtlSlotId(A1),spId(A4) ; sResource Id
|
||
MOVE.B DCtlExtDev(A1),spExtDev(A4) ; External Device <C523>
|
||
MOVE.W #0,spRefNum(A4) ; Reference number <C542>
|
||
MOVE.W #0,spIOReserved(A4) ; Reserved field, Must be zero now. <C671>
|
||
EXG.L A0,A4 ; Save A0 <C542>
|
||
_sUpdateSRT ; A0 contains ptr to spBlock, RefNum = 0 => closed <C542>
|
||
EXG.L A4,A0 ; Restore A0 <C542>
|
||
|
||
; Done
|
||
ADD.L #spBlockSize,SP ; deallocate spBlock
|
||
|
||
ENDWITH
|
||
|
||
@1 BRA.S UnLkStuff ; unlock everything <27Jun85>
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: Read
|
||
; Arguments: A0 (input) -- pointer to Read parameter block
|
||
; D1 (input) -- OS Call trap word
|
||
; D0 (output) -- error code
|
||
;
|
||
; Function: If the read call has the asynchronous flag bit set, it vectors
|
||
; to the driver to do the dirty work; otherwise it performs an
|
||
; asynchronous read call and polls the I/O control block until
|
||
; the I/O has completed.
|
||
;
|
||
;______________________________________________________________________
|
||
|
||
Read
|
||
TestFor SupportsIdle
|
||
BEQ.S @notsupported
|
||
_IdleUpdate ; this is activity, stay at full speed
|
||
@notsupported
|
||
|
||
MOVE.W IORefNum(A0),D2 ; get the refnum
|
||
BMI.S IORead ; if <0, its a device call
|
||
JMP FileRead ; let the file system handle it
|
||
|
||
IORead MOVEM.L D3-D5/A2-A4,-(SP) ; observe pascal regsave conventions <C133/29Aug86>
|
||
MOVEQ #ReadErr,D0 ; not-read-enabled error
|
||
MOVEQ #DReadEnable,D4 ; read enable flag bit number
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Routine: IORWCS
|
||
; Arguments: A0 (input) -- pointer to command parameter block
|
||
; D0 (input) -- operation-specific error code
|
||
; D1 (input) -- OS Call trap word
|
||
; D2 (input) -- the driver's RefNum
|
||
; D4 (input) -- flag enable bit for this command
|
||
; stack has D3-D4, A2 saved on it
|
||
; Called By: Read, Write, Control, Status
|
||
;
|
||
; Function: shares code for Read, Write, Control, and Status calls
|
||
; to IO Drivers; it maps the RefNum into a Device Control Entry
|
||
; pointer in A1, checks that the driver is enabled for such a
|
||
; call, and then handles the synchronous or asynchronous calling
|
||
; of the driver. If the NoQueue bit in the trap is set, it
|
||
; calls the driver directly without any queuing
|
||
;
|
||
;______________________________________________________________________
|
||
|
||
IORWCS
|
||
MOVE.L A0,D5 ; save param blk ptr (in case of MapUnit err)
|
||
BSR MapUnit ; first, map RefNum into DCE addr in A1
|
||
|
||
CMP.B #AWrCmd,D1 ; read or write?
|
||
BGT.S RWCSInit ; branch if status or control
|
||
CLR.L IONumDone(A0) ; nothing done so far
|
||
|
||
RWCSInit MOVE.W #1,IOResult(A0) ; set IOResult to "in progress"
|
||
MOVE.W D1,IOTrap(A0) ; set up IOCB: mark I/O command type
|
||
MOVE.W #IOQType,QType(A0) ; say its an I/O queueing element
|
||
|
||
BTST D4,DCtlFlags(A1) ; is driver enabled for this command?
|
||
MOVEM.L (SP)+,D3-D5/A2-A4 ; (clean up the stack) <C133/29Aug86>
|
||
BEQ.S RWCSDone ; give up if not
|
||
|
||
MOVEQ #NotOpenErr,D0 ; assume it's not open
|
||
BTST #DOpened,DCtlFlags+1(A1) ; is it open?
|
||
BEQ.S RWCSDone ; if not, exit ok
|
||
|
||
BTST #noQueueBit,D1 ; no queue bit set?
|
||
BNE DoImedIO ; if so, go right to the driver
|
||
|
||
BTST #asyncTrpBit,D1 ; async bit on?
|
||
BNE DoAsyncIO ; if so, don't wait for completion
|
||
|
||
CLR.L IOCompletion(A0) ; no completion routines for sync calls
|
||
MOVE.L A0,-(SP)
|
||
BSR DoAsyncIO
|
||
MOVE.L (SP)+,A0
|
||
|
||
SyncWait
|
||
MOVE.L jSyncWait,-(SP) ; get jump vector <C805>
|
||
RTS ; and jump to it <C805>
|
||
|
||
vSyncWait MOVE.W IOResult(A0),D0 ; test the sync completion flag <C805>
|
||
BGT.S vSyncWait ; <C805>
|
||
|
||
EXT.L D0 ; want long result <05Jun85>
|
||
|
||
RWCSDone MOVE.W D0, IOResult(A0) ; (in case driver was never called)
|
||
RTS
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: Write
|
||
; Arguments: A0 (input) -- pointer to Write parameter block
|
||
; D1 (input) -- OS Call trap word
|
||
; D0 (output) -- error code
|
||
;
|
||
; Function: If the write call has the asynchronous flag bit set, it vectors
|
||
; to the driver to do the dirty work; otherwise it performs an
|
||
; asynchronous write call and polls the I/O control block until
|
||
; the I/O has completed.
|
||
;
|
||
;______________________________________________________________________
|
||
|
||
Write
|
||
TestFor SupportsIdle
|
||
BEQ.S @notsupported
|
||
_IdleUpdate ; this is activity, stay at full speed
|
||
@notsupported
|
||
|
||
MOVE.W IORefNum(A0),D2 ; get the refnum
|
||
BMI.S IOWrite ; if <0, it's a device call
|
||
JMP FileWrite ; let the file system handle it
|
||
|
||
IOWrite MOVEM.L D3-D5/A2-A4,-(SP) ; observe pascal regsave conventions <C133/29Aug86>
|
||
MOVEQ #WritErr,D0 ; not-write-enabled error
|
||
MOVEQ #DWritEnable,D4 ; write enable flag bit number
|
||
BRA.S IORWCS
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: Control
|
||
; Arguments: A0 (input) -- pointer to Control parameter block
|
||
;
|
||
; Function: Call driver if control is enabled.
|
||
;
|
||
;______________________________________________________________________
|
||
|
||
ControlTrap MOVEM.L D3-D5/A2-A4,-(SP) ; observe pascal regsave conventions <C133/29Aug86>
|
||
MOVE.W IORefNum(A0),D2 ; get the refnum
|
||
MOVEQ #ControlErr,D0 ; not-control-enabled error
|
||
MOVEQ #DCtlEnable,D4 ; control enable flag bit number
|
||
BRA.S IORWCS
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: Status
|
||
; Arguments: A0 (input) -- pointer to Status parameter block
|
||
;
|
||
; Function: Call driver if status is enabled.
|
||
;
|
||
; 26-Apr-83 AJH implemented status call 1 -- return DCE handle
|
||
;
|
||
;______________________________________________________________________
|
||
|
||
StatusTrap MOVEM.L D3-D5/A2-A4,-(SP) ; observe pascal regsave conventions <C133/29Aug86>
|
||
MOVE.W IORefNum(A0),D2 ; test the sign of the refnum
|
||
MOVE.L A0,D5 ; save param blk ptr (in case of MapUnit err)
|
||
|
||
CMP #1,CSCode(A0) ; is it status call 1?
|
||
BEQ.S RetDCEHandle ; if so, special case it
|
||
|
||
MOVEQ #StatusErr,D0 ; not-status-enabled error
|
||
MOVEQ #DStatEnable,D4 ; status enable flag bit number
|
||
BRA.S IORWCS
|
||
|
||
RetDCEHandle
|
||
BSR MapUnit ; figure out the DCE handle (won't return if badunit #)
|
||
MOVE.L A2,CSParam(A0) ; return it as the result
|
||
BRA OpenOK ; restore registers and return
|
||
|
||
;____________________________________________________________________
|
||
;
|
||
; Ext Routine: KillIO
|
||
; Arguments: A0 (input) -- pointer to param block w/refNum
|
||
; D0 (output) -- result code
|
||
;
|
||
; Function: KillIO terminates the current request in progress
|
||
; for an I/O driver and empties its queue, posting
|
||
; error codes and running completion routines as
|
||
; appropriate.
|
||
;______________________________________________________________________
|
||
|
||
KillIOTrap
|
||
MOVEM.L D3-D5/A2-A4,-(SP) ; observe pascal regsave conventions <C133/29Aug86>
|
||
|
||
MOVE.W IORefNum(A0),D2 ; get the refNum
|
||
MOVE.L A0,D5 ; save param blk ptr (in case of MapUnit err)
|
||
BSR MapUnit ; derive the DCE pointer
|
||
MOVE.W #KillCode,CSCode(A0) ; KillIO maps to control call 1
|
||
|
||
MOVE SR,-(SP) ; preserve current status
|
||
ORI #HiIntMask,SR ; interrupts off for queue manipulation <24Jul85>
|
||
|
||
MOVEQ #DrvrCtl,D1 ; control routine offset within driver <19Mar85>
|
||
MOVEQ #ControlErr,D0 ; not-control-enabled error <19Mar85>
|
||
MOVEQ #DCtlEnable,D4 ; control enable flag bit number <19Mar85>
|
||
|
||
BTST D4,DCtlFlags(A1) ; is driver enabled for this command? <19Mar85>
|
||
BEQ.S KillFailed ; give up if not <19Mar85>
|
||
|
||
MOVEQ #NotOpenErr,D0 ; assume it's not open <19Mar85>
|
||
BTST #DOpened,DCtlFlags+1(A1) ; is it open? <19Mar85>
|
||
BEQ.S KillFailed ; if not, exit ok <19Mar85>
|
||
|
||
BSR GoDriver ; call the driver control routine
|
||
BNE.S KillFailed ; if that failed, punt
|
||
|
||
KillLoop TST.L DCtlQHead(A1) ; is there a request?
|
||
BEQ.S DoneKillIO ; if not, we're done
|
||
MOVEQ #AbortErr,D0 ; get the "abort" error code
|
||
MOVE #($2000+HiIntMask),D1 ; make PostCompletion stay at top level <24Jul85>
|
||
BSR PostCompletion ; post error code and dequeue
|
||
BRA.S KillLoop ; loop until done
|
||
|
||
DoneKillIO BSR DeActDrvr ; mark it inactive and unlock DCE, driver
|
||
MOVEQ #0,D0 ; no error
|
||
|
||
KillFailed MOVE (SP)+,SR ; interrupts back on
|
||
BRA OpenEnd ; restore regs and return to caller
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: DrvrInstall
|
||
; Arguments: D0 (input) -- Driver Refnum ( -1 thru -65 for common devices,
|
||
; D0 (output) -- result code, 0=driver installed
|
||
; A0 (input) -- pointer to driver to be installed.
|
||
;
|
||
; Function: Used to install a driver.
|
||
; A Device Control Entry for the driver is created and its
|
||
; handle entered into the specified Unit Table position (-1
|
||
; thru -32).
|
||
;
|
||
; If the unit number is -4 thru -9, the corresponding
|
||
; ROM-based driver will be replaced.
|
||
;
|
||
;______________________________________________________________________
|
||
|
||
DrvrInstall
|
||
MOVEM.L A2-A4/D3-D5,-(SP) ; observe Pascal regsave conventions <C133/29Aug86>
|
||
MOVE.L A0,A3 ; save name pointer
|
||
MOVE.L D0,D3 ; save refnum
|
||
BSR.S MpUnitNum ; make it a unit num
|
||
BMI.S DInstRTS ; exit if bad unit number
|
||
BNE.S ClearDCE ; if not nil, reuse it
|
||
|
||
BTST #asyncTrpBit,D1 ; async bit on? (use this for 'lock' indication)
|
||
BEQ.S @1 ; br if not
|
||
MOVEQ #DCtlEntrySize,D0 ; get size of device control entry
|
||
_ResrvMem ,SYS ; make room as low as possible (in case it gets locked forever)
|
||
|
||
@1 MOVEQ #DCtlEntrySize,D0
|
||
_NewHandle ,SYS ; allocate it on system heap
|
||
BNE.S DInstRTS ; exit on mem full errors
|
||
|
||
; clear out the DCE entry
|
||
|
||
ClearDCE MOVEQ #DCtlEntrySize-1,D0 ; get size in bytes
|
||
MOVE.L (A0),A1 ; DCE pointer
|
||
@1 CLR.B (A1)+ ; clear a byte
|
||
DBRA D0,@1 ; loop till cleared
|
||
|
||
; install it in the table
|
||
|
||
MOVE.L A0,(A2) ; DCE handle -> Unit I/O Table
|
||
MOVE.L (A0),A3 ; DCE pointer
|
||
BSET #DRamBased,DCtlFlags+1(A3) ; just set RAM-based until we load it
|
||
MOVE.W D3,DCtlRefNum(A3) ; set up the refNum (queue inited to 0s)
|
||
|
||
DInstOKExit MOVEQ #0,D0 ; no error
|
||
DInstRTS MOVEM.L (SP)+,A2-A4/D3-D5 ; restore regs <C133/29Aug86>
|
||
RTS
|
||
|
||
; routine to map the refNum into a DCE handle/pointer
|
||
|
||
MpUnitNum NOT.W D0 ; bitwise complement to get unitnum
|
||
BMI.S @1 ; br if it was positive
|
||
CMP.W UnitNtryCnt,D0 ; is it in range?
|
||
BGE.S @1 ; exit if not
|
||
|
||
ASL.W #2,D0 ; multiply by four
|
||
MOVE.L UTableBase,A2 ; get address of unit table
|
||
ADD D0,A2 ; add in the offset
|
||
MOVE.L (A2),A0 ; get the old DCE handle
|
||
MOVE.L A0,D0 ; was it nil?
|
||
|
||
_StripAddress ;ensure 32 bit valid address
|
||
TST.L D0 ;correct the condition codes <C540>
|
||
|
||
RTS ; return with A2=entry pointer, A0=handle
|
||
|
||
@1 MOVEQ #BadUnitErr,D0 ; flag the error
|
||
RTS
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: DrvrRemove
|
||
; Arguments: D0 (input) -- Driver Refnum (-1 thru -24)
|
||
; D0 (output) -- result code, 0=driver removed
|
||
; -1=driver not found
|
||
;
|
||
; Function: Used to remove a driver. A RAM-based driver is purged from
|
||
; the system heap using a ReleaseResource call. Memory for
|
||
; the Device Control Entry for the driver is disposed and the
|
||
; driver's close routine is called.
|
||
;________________________________________________________________________
|
||
|
||
DrvrRemove
|
||
MOVEM.L A2-A4/D3-D5,-(SP) ; observe Pascal regsave conventions <C133/29Aug86>
|
||
BSR.S MpUnitNum
|
||
BMI.S DInstRTS ; exit if error
|
||
BEQ.S DInstOKExit ; exit if entry is empty (already removed)
|
||
|
||
MOVE.L A2,A3 ; save entry pointer
|
||
MOVE.L D0,A2 ; DCE handle
|
||
MOVE.L (A2),A1 ; DCE pointer
|
||
|
||
; A3 = ptr to UnitTable Entry
|
||
; A2 = DCE handle
|
||
; A1 = DCE ptr
|
||
|
||
BTST #DOpened,DCtlFlags+1(A1) ; check if it's Opened
|
||
BNE.S RemovErr ; don't remove an opened driver
|
||
BTST #DRAMBased,DCtlFlags+1(A1) ; check if it's RAM-based
|
||
BEQ.S @1 ; branch for ROM-based drivers
|
||
|
||
MOVE.L DCtlDriver(A1),-(SP) ; driver object handle
|
||
_ReleaseResource ; go remove it
|
||
|
||
@1 MOVE.L A2,A0 ; deallocate DCE handle
|
||
_DisposHandle ,SYS ; dispose it on system heap
|
||
CLR.L (A3) ; clear Unit Table entry
|
||
BRA.S DInstOKExit ; and exit successfully
|
||
|
||
RemovErr MOVEQ #DRemovErr,D0 ;
|
||
BRA.S DInstRTS ; restore regs and exit
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Ext Routine: AddDrive
|
||
; Arguments: D0 (input) -- high word: drive number
|
||
; low word: driver refnum
|
||
; (output) -- error code (0)
|
||
; A0 (input) -- Drive Queue element ptr
|
||
;
|
||
; Function: Add a drive to the drive queue.
|
||
;
|
||
; To Do:
|
||
; - adjust drive number if conflict (or replace??)
|
||
;________________________________________________________________________
|
||
|
||
AddDriveTrap MOVE.L D0, DQDrive(A0)
|
||
LEA DrvQHdr, A1
|
||
JSR EnqueueTrap ; <06Mar85>
|
||
MOVEQ #0, D0 ; return success for now <06Mar85>
|
||
RTS ; <06Mar85>
|
||
|
||
END
|
||
|
||
|