mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-07 20:29:52 +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.
607 lines
20 KiB
Plaintext
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
|
|
|
|
|