boot3/OS/SCSIMgr4pt3/XPT.a
Elliot Nunn 5b0f0cc134 Bring in CubeE sources
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.
2017-12-26 10:02:57 +08:00

607 lines
20 KiB
Plaintext

;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
; File: XPT.a
;
; Contains: SCSI Mgr for the 53c96/
;
; Written by: Paul Wolf
;
; Copyright: © 1990-1994 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM21> 1/31/94 DCB Added a semaphore to the SCSIBusy stuff so we don't call
; DeferUserFn from enable VM as much.
; <ML4> 1/9/94 pdw Took out aerror on build SCSIBusy patch with forROM.
; <ML3> 1/5/94 pdw Simplifying the SCSIBusy install stuff.
; <ML2> 1/5/94 pdw (DCB) Added SCSIBusy patch.
; <SM19> 12/19/93 DCB Added SetIntsAt2 and RestoreInts.
; <SM18> 11/22/93 pdw Rolling in from <MCxx>.
; <MC8> 11/10/93 pdw Added clearing of inDebugger flag.
; <MC7> 11/8/93 pdw Changed recording criteria around call to completion routine.
; <MC5> 10/14/93 pdw Fixing the occasional calling of completion routines at level 7
; bug. I was jumping to @call instead of @enableIntCall
; <SM17> 11/5/93 pdw Fixed build.
; <SM16> 11/5/93 pdw Series of attempts and re-attempts to fix various VM/FileShare
; problems. Finally ended up fixing it all at the very source of
; the problem - the File System!
; <SM15> 10/14/93 pdw <MC> roll-in.
; <MC4> 10/12/93 pdw Fixed bug where we would blow away our deferred task if we got
; another completion routine before we dispatch that task.
; <MC3> 10/12/93 pdw Added support for Synchronous data transfers, rewrote State
; Machine, message handling etc.
; <MC2> 10/6/93 pdw Removed call to DTInstallHead, instead doing it with ENQUEUEHEAD
; directly.
; <SM14> 9/12/93 pdw Changed the way I do the deferring of completion routines. I
; now check for inVBL rather than VM because that is how VM
; disables the DTQ. Also enqueue my task at the head of the DTQ.
; <SM13> 9/9/93 pdw Lots of little changes. Name changes, temporary cache_bug
; stuff.
; <SM12> 7/8/93 pdw Getting rid of useless InitXPTRecorder function.
; <SM11> 6/29/93 pdw Massive checkins: Change asynchronicity mechanism to CallMachine
; stack switching mechanism. Adding support for Cold Fusion.
; Rearranging HW/SW Init code. Some code optimizations.
; <SM10> 5/25/93 DCB Rollin from Ludwig. (The next two items below)
; <LW11> 5/21/93 PW Changing how we detect the presence of VM. Now using $B78 < 0
; instead of $CF0==-1.
; <LW10> 5/20/93 DCB Added ciDebuggerPatch. This is a patch to _DebugUtil which
; prevents deferred completion routines from occuring when we are
; in a debugger.
; <SM9> 5/5/93 PW Converted names to meanies-friendly names. Updated with latest
; from Ludwig stuff.
; <LW8> 4/14/93 DCB Added RemoveSyncWait and synced up with SuperMario
; <SM8> 3/29/93 PW Added an equate to better handle different movems.
; <SM7> 3/29/93 PW Added a return address RECORD_EVENT to catch the driver messing
; up the stack problem.
; <LW7> 3/26/93 mal (PW) Another try.
; <LW6> 3/26/93 mal (actually PW)Removed the bogus "fix" that I just put in.
; <LW5> 3/26/93 PW Removed RECORD_ON definition here since I put it in Debug.a.
; Fix last minute VM bug (this is what I get for checking in files
; after staying up all night).
; <LW4> 3/26/93 PW Fixing RECORD_ON problem.
; <LW3> 3/26/93 PW Adding code to defer completion routine if int level!=0 and
; DeferTask Q is empty and DeferredTask Manager is not busy (i.e.
; not working on the Q) and VM isn't running.
; <SM5> 1/31/93 PW Update from the latest of Ludwig. Also changes required for PDM
; (will update Ludwig with these as needed myself).
; <LW2> 1/30/93 PW Added glue code for calling completion routines (saving
; registers that were getting trashed by File Manager).
; <SM4> 11/20/92 PW Added some Includes that were removed from headers.
; <SM3> 11/3/92 PW Removed unneeded intrRegs definition.
; <SM2> 10/30/92 DCB Misc Interrupt handling changes to reduce interrupt latency.
;
;==========================================================================
MACHINE MC68020
BLANKS ON
PRINT OFF
LOAD 'StandardEqu.d'
INCLUDE 'Debug.a'
INCLUDE 'ACAM.a'
INCLUDE 'XPTEqu.a'
PRINT ON
CASE OBJECT
IMPORT RecordEvent ; Recorder.a
IMPORT VMDisableUserCode, VMEnableUserCode
IMPORT ENQUEUEHEAD
IF forROM THEN ;¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
InitXPTAsm PROC EXPORT ; initialize SCSIGlobals based XPT globals
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
move.l SCSIGlobals, A1 ; use A1 as base
rts
NAME 'InitXPTAsm'
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
RemoveSyncWait PROC EXPORT ; RemoveSyncWait(XPTg)
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
; Possible problem - what if sombody else patched vSyncWait in
; the meantime? We are going to stuff the old one back in!!!
;
move.l 4(sp), a0 ; get ptr to XPTglobals
move.l XPTglobals.OldSyncWait(A0),jSyncWait ; put the old syncWait back
rts
NAME 'RemoveSyncWait'
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
InitSyncWait PROC EXPORT ; InitSyncWait(XPTg)
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
move.l 4(sp), a0 ; get ptr to XPTglobals
move.l jSyncWait, XPTglobals.OldSyncWait(A0)
lea CI_vSyncWait, A0
move.l A0, jSyncWait
rts
NAME 'InitSyncWait'
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
CI_vSyncWait
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
trashedRegs REG D0-D2/A0-A1/A5
sizeofTrashedRegs EQU 6*4
IMPORT InterruptLevel
move.w IOResult(A0), D0 ; test for completion
ble.s @fastWayOut ;
lea -4(sp), sp ; make room for return address (jmp to oldSyncWait)
movem.l trashedRegs, -(sp) ; save registers trashed by C routines and A5
GetXPTg ; into A5
IF 0 AND RECORD_ON THEN
pea 'Isyw'
move.l A0, -(sp)
bsr RecordEvent
addq.l #8, sp
ENDIF
@wait
CASE ON ;¥
IMPORT CheckInterrupts
move.l A0, -(sp)
move.l A5, -(sp) ; push XPTg parameter
bsr CheckInterrupts
addq.l #4, sp
move.l (sp)+, A0
CASE OBJECT ;¥
move.w IOResult(A0), D0 ; test for completion
bgt.s @wait
@endWait
move.l XPTglobals.OldSyncWait(A5), sizeofTrashedRegs(sp)
movem.l (sp)+, trashedRegs
rts ; rts's to old vSyncWait - not to caller
@fastWayOut
lea -4(sp), sp ; make room for return address (jmp to oldSyncWait)
move.l A5, -(sp)
GetXPTg ; into A5
move.l XPTglobals.OldSyncWait(A5), 4(sp)
move.l (sp)+, A5
rts ; rts's to old vSyncWait - not to caller
NAME 'CI_vSyncWait'
; Note:IntRegs reg a0-a3/d0-d3 ; registers saved by InterruptHandlers.a
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
XPT_ISR0 PROC EXPORT ; void XPT_ISR0 (void)
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
bsr VMDisableUserCode ; disable user code (so page faults won't happen)
IF INDEXED_IS_FASTER THEN
move.l ([SCSIGlobals],SCSIGlobalsRec.xptGlobals), A0
move.l XPTglobals.BusInfoPtrs+ 0 (A0), A0 ; ptr to initInfo
move.l BusInfo.initInfo.SIMstaticPtr(A0), -(sp) ; SIMg parameter
jsr ([BusInfo.initInfo.SIM_ISR, A0]) ; SIM_ISR call
ELSE
move.l SCSIGlobals, A0
move.l SCSIGlobalsRec.xptGlobals(A0), A0
move.l XPTglobals.BusInfoPtrs+ 0 (A0), A0 ; ptr to initInfo
move.l BusInfo.initInfo.SIMstaticPtr(A0), -(sp)
move.l BusInfo.initInfo.SIM_ISR(A0), A0
jsr (A0)
ENDIF
addq.l #4, sp
bra VMEnableUserCode ; enable user code (allow page faults)
;rts from VMEnableUserCode
RTSNAME 'XPT_ISR0'
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
XPT_ISR1 PROC EXPORT ; void XPT_ISR1 (void)
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
bsr VMDisableUserCode ; disable user code (so page faults won't happen)
IF INDEXED_IS_FASTER THEN
move.l ([SCSIGlobals],SCSIGlobalsRec.xptGlobals), A0
move.l XPTglobals.BusInfoPtrs+ 4 (A0), A0 ; ptr to initInfo
move.l BusInfo.initInfo.SIMstaticPtr(A0), -(sp) ; SIMg parameter
jsr ([BusInfo.initInfo.SIM_ISR, A0]) ; SIM_ISR call
ELSE
move.l SCSIGlobals, A0
move.l SCSIGlobalsRec.xptGlobals(A0), A0
move.l XPTglobals.BusInfoPtrs+ 4 (A0), A0 ; ptr to initInfo
move.l BusInfo.initInfo.SIMstaticPtr(A0), -(sp)
move.l BusInfo.initInfo.SIM_ISR(A0), A0
jsr (A0)
ENDIF
addq.l #4, sp
bra VMEnableUserCode ; enable user code (allow page faults)
;rts from VMEnableUserCode
RTSNAME 'XPT_ISR1'
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
InterruptLevel PROC EXPORT
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
move.w SR, D0
and.w #$0700, D0
lsr.w #8, D0
rts
NAME 'InterruptLevel'
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
SetIntsAt2 PROC EXPORT
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
move.w SR, D0
or.w #$0200, sr
and.w #$FEFF, sr
rts
NAME 'SetIntsAt2'
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
RestoreInts PROC EXPORT
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
move.w 6(sp), SR
rts
NAME 'RestoreInts'
ENDP
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
getCurrentA5 PROC EXPORT
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
move.l a5, D0
rts
NAME 'getCurrentA5'
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
restoreCurrentA5 PROC EXPORT
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
move.l 4(sp), a5
rts
NAME 'restoreCurrentA5'
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
ciDebuggerPatch PROC EXPORT
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; Since debuggers have a tendency to turn off the deferred task manager
; we will deadlock if the debugger does file I/O (like a log in MacsBug).
; To prevent this problem we patch the entering and exiting debugger
; procedures in _DebugUtil
; WARNING, the KillXPT routine relies on @enabled being 4 bytes before @patch!!!
bra.s installDebuggerPatch
topPatch equ *
lea @enabled,a0 ; local storage
move.l #1,(a0) ; remember that we are enabled
lea @address,a0 ; address of old _DebugUtil
move.l 4(sp),(a0) ; save it in local storage
lea @patch,a0 ; the address of the patch
move.l a0,d0 ; return it to caller
rts
@address dc.l 0 ; address of old _DebugUtil
@enabled dc.l 0 ; enabled marker
@patch
move.l a5,-(sp) ; save a5
move.l SCSIGlobals, A5 ; aquire our globals
lea @enabled,a2 ; get enabled variable (a2 is saved but not a parameter)
tst.l (a2) ; Are we running?
beq.s @exit
cmp.b #2,d0 ; something we are interested in?
bhi.s @exit ; nope, outta here
beq.s @leaving ; leaving debugger?
tst.b d0 ; debuggerMax?
beq.s @exit ; yep, we don't do anything with this
@entering
addq.b #1, SCSIGlobalsRec.inDebugger(A5) ; inc counter
bra.s @exit
@leaving
subq.b #1, SCSIGlobalsRec.inDebugger(A5) ; dec counter
@exit
move.l (sp)+,a5 ; restore a5
move.l @address,a2 ; address of old _DebugUtil
jmp (a2)
RTSNAME 'debuggerPatch'
sizePatch equ *-topPatch
installDebuggerPatch
clr.b ([SCSIGlobals],SCSIGlobalsRec.inDebugger) ; clear counter
move.l #sizePatch,d0 ; size of patch
_NewPtrSys ; get storage for it
bne.s @failInst ; failed install get out
move.l a0,-(sp) ; save a0
move.l #sizePatch,a1 ; length of patch
_DebuggerLockMemory ; lock the memory
move.l (sp)+,a1 ; restore a0 into a1 since it is the destination for BlockMove
lea topPatch,a0 ; source for BlockMove
move.l #sizePatch,d0 ; length for BlockMove
_BlockMove ; BlockMove it into RAM (and flush cache)
jmp (a1) ; finish setting up (rts from there)
@failInst moveq #0,d0 ; nil ptr (we didn't install a patch)
rts
NAME 'installDebuggerPatch'
ENDP
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
CallCompRoutineGlue PROC EXPORT
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; Note: This routine is needed for a couple of reasons.
; 1) because the file manager's BasicIO ioCompletion routine wipes out D2-D3
; and A0-A3. This filters up through the driver's scsiCompletion routine
; because it made the call to ioDone simply by jmping to it (and not worrying
; about any registers). We have changed our driver to save these registers
; as well but for paranoias sake, we do it here too (3rd-party drivers etc.)
; 2) because we want to run completion routines at level 0 if possible. This is
; done through the deferred task manager. To avoid deadlocks, we check for
; conditions that would prevent deferred tasks from running - if present, we
; will execute the completion routines immediately.
;
; 8(sp) ioPtr
; 4(sp) scsiCompletion
; 0(sp) return address
;
complTrashedRegs REG D3/A2-A3/A5
StackFrame RECORD {currentSP},DECR
completionDT ds.l 1
ioPtr ds.l 1
currentSP ds.l 1
ENDR
IF 0 THEN
move.w sr, D0 ; what interrupt level are we?
move.w D0, D1
and.w #$700, D1
beq.s @call ; if 0 -> call routine now
move.l SCSIGlobals, A1
tst.b SCSIGlobalsRec.inDebugger(A1) ; are we in a debugger?
bne.s @call ; yes -> call immediately
or.w #$700, sr ; else, block all ints temporarily
; Check to see if it's safe to install our deferred task. That is, can we be guaranteed
; that it will run before another synchronous request happens. This could occur from
; a VBL or from a Deferred Task so we need to see if either of these are busy.
; Note that VM will turn off the DTQ (and VBLs) by setting the inVBL bit.
btst #inVBL, VBLQueue+QFlags ; DTQ blocked because of VBL busy?
bne.s @enableIntCall ; yes -> call immediately
btst #InDTQ, DTQFlags ; already in dispatcher?
bne.s @enableIntCall ; yes -> call now then
; NOT We no longer care if there are any Deferred Tasks already enqueued because now we go
; and install ourselves at the beginning of the DTQ. Not very friendly but it will
; work as long as nobody else does the same thing.
move.l DTQueue+2, D1 ; is Q empty?
bne.s @enableIntCall ; no -> call now then
move.l StackFrame.completionDT(sp), A0 ; get addr of def.task
move.l StackFrame.ioPtr(sp), dtParm(A0) ; ioPtr is dtParm
IF RECORD_ON THEN
pea 'dfrC'
move.l dtParm(A0), -(sp)
bsr RecordEvent
addq.l #8, sp
ENDIF
move.w D0, -(sp) ; save SR
lea DTQueue, A1 ; get ptr to queue
bsr.l ENQUEUEHEAD ; go add element
move.w (sp)+, sr ; unblock ints
rts
@enableIntCall
move.w D0, sr ; unblock ints
ENDIF
@call
IF CALL_RECORD_ON THEN
pea 'imC-'
move.w sr, -(sp)
move.w DTQFlags, -(sp)
bsr RecordEvent
addq.l #8, sp
ENDIF
move.l StackFrame.ioPtr(sp), A1 ; get ioPtr from stack
movem.l complTrashedRegs, -(sp)
move.l A1, -(sp) ; A1 is ioPtr
move.l SCSI_IO.scsiXPTprivate(A1), A5 ; get client's A5
move.l SCSI_IO.scsiCompletion(A1), A1 ; get completion routine
jsr (A1) ; call completion routine
movem.l (sp)+, complTrashedRegs
IF CALL_RECORD_ON THEN
pea '-imC'
move.l sp, -(sp)
bsr RecordEvent
addq.l #8, sp
ENDIF
rts
NAME 'CallCompRoutineGlue'
ENDP
DEFERREDCALL PROC EXPORT
dtTrashedRegs REG D0-D7/A0-A6
dtTrashedRegsSize equ 15*4
movem.l dtTrashedRegs, -(sp)
move.l A1, -(sp) ; A1 is dtParm (ioPtr)
move.l SCSI_IO.scsiXPTprivate(A1), A5 ; get client's A5
IF RECORD_ON THEN
pea 'dtC-'
move.w SCSI_IO.scsiXPTprivate(A1), -(sp)
move.w 8(sp), -(sp) ; low word of ioPtr
bsr RecordEvent
addq.l #8, sp
ENDIF
jsr ([SCSI_IO.scsiCompletion,A1]) ; call completion routine
IF RECORD_ON THEN
pea '-dtC'
move.l A1, -(sp)
bsr RecordEvent
addq.l #8, sp
pea 'retA'
move.l dtTrashedRegsSize+8(sp), -(sp)
bsr RecordEvent
addq.l #8, sp
ENDIF
movem.l (sp)+, dtTrashedRegs
rts
NAME 'DEFERREDCALL'
ENDP
ENDIF ;¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
ciBusyPatch PROC EXPORT
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; Because we are deferring our data transfer routines in places where we are
; not re-entrant we will use the SCSIBusy mechanism to tell the File Manager
; whether we are re-entrant or not. The old SCSIBusy patch remains in the chain
; and fully functional. When our patch is executed it checks if SyncUnsafe is
; not zero and if so returns busy and remembers that the file system was attempting
; use the SCSI Manager when it wasn't safe. Then when EnableVM determines that
; we are safe again it checks the wasBusy flag and calls jvSCSIFreeHook to wake
; the file system up again.
;
; WARNING, the KillXPT routine relies on @enabled being 4 bytes before @patch!!!
bra.w installBusyPatch
topBusyPatch equ *
lea @enabled,a0 ; local storage
move.l #1,(a0) ; remember that we are enabled
lea @address,a0 ; address of old _SCSIDispatch
move.l 4(sp),(a0) ; save it in local storage
lea @patch,a0 ; the address of the patch
move.l a0,d0 ; return it to caller
rts
@address dc.l 0 ; address of old _SCSIDispatch
@enabled dc.l 0 ; enabled marker
@patch
move.l a5,-(sp) ; save a5
move.l SCSIGlobals, a5 ; aquire our globals
lea @enabled,a0 ; get enabled variable (a2 is saved but not a parameter)
tst.l (a0) ; Are we running?
beq.s @exit
cmpi.w #OldSCSICalls.kSCSIBusy, 8(sp) ; check selector after the return addr and saved A5
bne.s @exit ; not scsiBusy
move.l a4, -(sp) ; save a4
move.l SCSIGlobalsRec.xptGlobals(a5), a4 ; get XPTg for syncUnsafeCount
tst.w XPTglobals.syncUnsafeCount(a4) ; unsafe?
beq.b @a4Exit ; nope, pass through to regular SCSIBusy
bset.b #0,SCSIGlobalsRec.ciWasBusy(a5) ; remember that we returned busy
move.l (sp)+,a4 ; restore a4
move.l (sp)+,a5 ; restore a5
move.l (sp)+,a0 ; return address
adda.w #2,sp ; pop selector
move.w #1,(sp) ; return busy (pascal style return value on stack)
jmp (a0) ; return to client
@a4Exit
move.l (sp)+,a4 ; restore a4
@exit
move.l (sp)+,a5 ; restore a5
move.l @address,a0 ; address of old _SCSIDispatch
jmp (a0) ; call thru to old
RTSNAME 'busyPatch'
sizeBusyPatch equ *-topBusyPatch
installBusyPatch
move.l SCSIGlobals, a0 ; aquire our globals
clr.b SCSIGlobalsRec.ciWasBusy(a0) ; initialize
clr.b SCSIGlobalsRec.ciBusyPending(a0) ; initialize
move.l #sizeBusyPatch,d0 ; size of patch
_NewPtrSys ; get storage for it
bne.s @failInst ; failed install get out
move.l a0,-(sp) ; save a0
move.l #sizeBusyPatch,a1 ; length of patch
_DebuggerLockMemory ; lock the memory
move.l (sp)+,a1 ; restore a0 into a1 since it is the destination for BlockMove
lea topBusyPatch,a0 ; source for BlockMove
move.l #sizeBusyPatch,d0 ; length for BlockMove
_BlockMove ; BlockMove it into RAM (and flush cache)
jmp (a1) ; finish setting up (rts from there)
@failInst moveq #0,d0 ; nil ptr (we didn't install a patch)
rts
NAME 'installBusyPatch'
ENDP
END