mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +00:00
1669 lines
62 KiB
Plaintext
1669 lines
62 KiB
Plaintext
************************************************************************
|
||
;
|
||
; File: CudaMgr.a
|
||
;
|
||
; Contains: Contains low level code to support sending and receiving
|
||
; packets (ADB, Pseudo Commands, Ticks, etc) to/from the Cuda
|
||
; 6805uC. Uses some common routines that are in EgretMgr.a and
|
||
; EgretPatches.a. The Egret/Caboose Firmware and the Cuda firmware
|
||
; use the same globals area and parameter blocks.
|
||
;
|
||
;
|
||
; Written by: Gary Rensberger
|
||
; Modified by: Gus Andrade
|
||
; Cuda Port by: Ray Montagne
|
||
; Modified by: Greg Schroeder
|
||
;
|
||
; Copyright © 1990-1993 by Apple Computer, Inc. All rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM14> 11/9/93 KW added some eieioSTP macros. Only expands for CygnusX1 ROM
|
||
; <SM13> 9/29/93 SAM From mc900ftjesus.
|
||
; <MC2> 9/25/93 SAM Sucked over CudaDispatch from CudaMgrPatch.a (in the Gibbly).
|
||
; <SM12> 6/14/93 kc Roll in Ludwig.
|
||
; <LW8> 6/11/93 chp Enabling interrupts too broadly across the Cuda Manager results
|
||
; in frequent system hangs when using LocalTalk. Extensive
|
||
; performance analysis indicates that Cuda Manager interrupt
|
||
; latency is worst when calling _CudaDispatch with interrupts
|
||
; masked (see also: the Reliability Manager) and in the loop
|
||
; waiting for the first byte of a command packet to shift out of
|
||
; the VIA. SCC interrupts are now reenabled just before this wait
|
||
; loop, but not in CudaShiftRegisterIRQ.
|
||
; <LW7> 5/21/93 GS (chp,mal,fau) Really fixed the LW6 fix of making sure the
|
||
; interrupt level moves from 7 back down to 3 after the first byte
|
||
; of the transaction has been moved into the Shift Reg in
|
||
; CudaDispatch.
|
||
; <LW6> 5/14/93 GS Changed the interrupt level from level 3 to 7 around some time
|
||
; critical code during the sample of the TReq line and moving the
|
||
; first byte of a transaction into the SR of the VIA.
|
||
; <LW5> 5/10/93 chp During Cuda transactions, disable interrupts only through level
|
||
; 3 instead of through level 6. This markedly improves handling of
|
||
; MIDI, DMA, and DSP interrupts. Fixes RADAR #1059613. Reviewed by
|
||
; God and both houses of Parliament.
|
||
; <LW4> 1/28/93 mal Fixed typo where D7 used instead of D0. Fixes bug #1062496.
|
||
; <LW3> 1/14/93 GS Fix a mis-typed label.
|
||
; <LW2> 1/14/93 GS (RBM) Fix the occassional hang at boot. When outputing from
|
||
; the VIA to Cuda, the interrupt will occur prior to the rising
|
||
; edge of CB1. Delay long enough for the edge to occur before
|
||
; acknowledging the shift register interrupt.
|
||
; <SM11> 11/20/92 GS Removed the support for the Cuda PDMsgs by removing routines
|
||
; CudaPDMPatch, CudaKeyBdSwHandler, and associated routines. This
|
||
; function is now handled by the Gibbly.
|
||
; <SM10> 11/5/92 SWC Changed ShutdownEqu.a->Shutdown.a.
|
||
; <SM9> 10/20/92 fau Changed CudaInit to use A2 instead of A1. This was required
|
||
; because routines in Universal.a that happenned after the call to
|
||
; CudaInit were depending on A1 being set up.
|
||
; <SM8> 10/8/92 GS Added code to the KeybdSwHnadler to inhibit calls to the
|
||
; OSDispatcher if the Trap is not yet installed by the System.
|
||
; <SM7> 10/7/92 GS [RBM,TJR] Added call to initialize vector in Cuda manager
|
||
; globals with pointer to the power message resume procedure.
|
||
; Added dispatch selector to execute the power message resume
|
||
; procedure.
|
||
; Needed to initialize the high word of d7 before going to
|
||
; Error1Handler.
|
||
; If interrupts get disabled while Cuda is in the process of
|
||
; generating an IDLE acknowledge, a subsequent attention byte
|
||
; could cause the IDLE acknowledge and ATTENTION byte to be
|
||
; appended into the current response packet.
|
||
; Changed the handling of response packets such that when the last
|
||
; byte has been received, the Cuda manager will wait for the IDLE
|
||
; acknowledge (should occur within 71.5µS minimum of negation of
|
||
; TIP).
|
||
; <SM6> 9/18/92 GS Re-Enable the CudaEnableKeybdNMI routine because of the Vector
|
||
; table. Cuda No longer uses this routine, but there was a vector
|
||
; set aside for it. This needs to be addressed in a later version
|
||
; of the ROM.
|
||
; <SM5> 9/18/92 GS (rbm) If interrupts get disabled while Cuda is in the process
|
||
; ofgenerating an IDLE acknowledge, a subsequent attention byte
|
||
; could cause the IDLE acknowledge and ATTENTION byte to
|
||
; beappended into the current response packet. Changed the
|
||
; handling of response packets such that when the last byte has
|
||
; been received, the Cuda manager will wait for the IDLE
|
||
; acknowledge (should occur within 71.5µS minimum of negation of
|
||
; TIP).
|
||
; (gaa/rbm) Modified CudaInit to check if Cuda was trying to start
|
||
; a transaction prior to starting the Sync Ack process. This
|
||
; fixed a bug where DeadCuda was called because the timeout would
|
||
; be reached because
|
||
; Cuda was trying to start a transaction and the system side
|
||
; thought that it was in the middle of a Sync Ack cycle.
|
||
; Update Tickle Timer to 160 count. Decr Timer in Cuda FW is at
|
||
; 16cnts/sec.
|
||
; Remove Completion routine in TickleCuda routine.
|
||
; <SM5> 8/24/92 GS Added code in the IRQDispatcher to fix the bug that passed back
|
||
; data in a Read6805 request, when the data bytes reqquessted was
|
||
; zero. The fix will chk the recvDataCnt var of the Parm blk before
|
||
; placing data in the recv buffer ptr.
|
||
; <SM4> 6/30/92 GS Fixed a problem in the Cuda Dispatcher. If a collision occurs,
|
||
; wait for the busy state flag to be cleared by the IdleAck
|
||
; handler before accepting another command. This problem causes
|
||
; the ADB transactions to get out of sync and the system will
|
||
; hang.
|
||
; <SM3> 6/26/92 GS (RBM) Updated 'SetTransferParams' so that special setup for
|
||
; 'RdWrIIC' is performed. This command requires a non conforming
|
||
; parameter
|
||
; block in that the EgretPB.ByteCnt requires the number of bytes
|
||
; to send prior to the data portion of the IIC transaction and
|
||
; EgretPB.BufPtr points to a pString. On write, the pString
|
||
; contains the data to write while on read operations, the pString
|
||
; contains only a count of bytes to read. Data is then returned
|
||
; inthe pString.
|
||
; Removed Cuda Cmds to enable Keyboard NMI, and IIC mode. These
|
||
; are no longer need, because KeyboardNMI now defaults to Enabled.
|
||
; SetDFACorIIC mode is no longer a command. IIC and DFAC both use
|
||
; use the Data and Clk pins in the same mode.
|
||
; EnableWakeUpMode is now done with a CDev.
|
||
;
|
||
; <SM2> 5/25/92 RB Removed definition of 'CUDA' since it has a conflict with
|
||
; another symbol and it is not used anyway. Also got rid of
|
||
; 'branch to next instruction warning.
|
||
; <1> 5/22/92 RB first checked in
|
||
; <SM1> 5/21/92 RB First Checked in. Got rid of OverPatch area and PadForOverPatch
|
||
; conditionals.
|
||
; <P4> 3/23/92 GS Fixed bug in code rolled in from the Regatta System files in
|
||
; the CudaShiftRegIRQ routine. Incorrectly, entered the
|
||
; tickcompletion routine with bogus values then placed into the
|
||
; TIME lomem
|
||
; <P3> 3/3/92 GS Updated the INIT of Cuda to include the IIC and Wakeup modes.
|
||
; Also added the Enable Keybd NMI cmd to CudaINIT.
|
||
; <P2> 2/10/92 GS Cleaned up some comments. Must return here to add in code for
|
||
; checks of the use of DFAC or IIC mode used on Cuda depending on
|
||
; machine type.
|
||
; <1> 1/16/92 GS first checked in
|
||
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
; Pre-Pandora ROM comments begin here.
|
||
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
; Previous history
|
||
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
; Changes for Cuda:
|
||
; {9} 08/21/91 gjs added patch to align code in Egret/Cuda Dispatch code. Patch
|
||
; placed in CudaPatches.a
|
||
; {8} 07/30/91 gjs Preserved/Restored status register on calls to the completion
|
||
; routines in ShiftRegIRQ routine at @Implicit, and at routine
|
||
; delay100us
|
||
; {7} 07/03/91 gjs Overpatched the CudaInit code into CudaPatchesToo.a
|
||
; added Export DeadCuda
|
||
; {6} 06/24/91 gjs Rolled the Cuda Manager changes into Terror
|
||
; <5> 2/20/91 BG Fixed error in CheckPacket. The check for allowable
|
||
; pseudo-packets was a hard-coded name check instead of an
|
||
; end-of-table check.
|
||
; <4> 12/11/90 JJ Mac LC: Changes references to VISAChipBit to V8ChipBit.
|
||
; <3> 12/7/90 CCH Adjusted the patch code in CheckPacket so that it fits in the
|
||
; same number of bytes as the original code.
|
||
; <2> 12/6/90 BG (with GA) Rolled in Eclipse-related Egret/Caboose changes.
|
||
;
|
||
; <01> 12/6/90 RBM Ported Cuda manager from Egret manager <Eclipse version>.
|
||
; Due to major changes in the transaction protocol, Egret is no longer supported.
|
||
; ROM builds should include IF HasCUDA for startinit & diagnostics.
|
||
; Changed handshake protocol to implement CUDA. Eliminated timed
|
||
; assertions/negations & inverted polarity of handshake lines that
|
||
; are controlled by the system. Handshake line signal names have
|
||
; been changed to avoid confusion in usage. Added an Idle State
|
||
; acknowledgement after termination of a response packet transaction.
|
||
; Exit from ShiftRegIrq now restores the interrupt mask on exit from
|
||
; transmission of command packet data.
|
||
;
|
||
; Restructured code in ShiftRegIrq so that testing the TReq handshake
|
||
; line does not occur after manipulation of TIP or ByteAck.
|
||
;
|
||
; CudaInit no longer needs to send a NOP command to turn off the
|
||
; asynchronous transaction sources on ReBoot. This function is
|
||
; performed through a 'SYNC' handshake sequence which disables
|
||
; all asynchronous message sources.
|
||
;
|
||
; Exported routines are in a jump table so that any future overpatching
|
||
; may be a little easier to implement.
|
||
;
|
||
************************************************************************
|
||
machine mc68020
|
||
|
||
BLANKS ON
|
||
STRING ASIS
|
||
|
||
PRINT OFF
|
||
LOAD 'StandardEqu.d'
|
||
INCLUDE 'HardwarePrivateEqu.a'
|
||
INCLUDE 'UniversalEqu.a'
|
||
INCLUDE 'DebugMonEqu.a'
|
||
INCLUDE 'ShutDown.a'
|
||
include 'EgretEqu.a'
|
||
PRINT ON
|
||
eject
|
||
|
||
CudaMgr PROC EXPORT ; { CudaMgr Proc
|
||
|
||
EXPORT CudaDispatch, SendCudaCmd, CudaInit
|
||
EXPORT CudaTickHandler, CudaShiftRegIRQ
|
||
|
||
IMPORT GetHardwareInfo, Error1Handler
|
||
IMPORT SetResponseParams, CheckPacket
|
||
IMPORT PseudoCntTable,ADBCntTable
|
||
|
||
CudaDebug EQU 1 ; Enables Debug features during development
|
||
ErrCudaInit equ $0030 ; TEMPORARY definition of error equate defined in STEQU.a
|
||
|
||
|
||
WITH EgretGlobals,EgretPB,RespHeader
|
||
eject ; { With
|
||
;________________________________________________________________________________________________
|
||
; Routine: CudaDispatch 8f90
|
||
;
|
||
; Function: This is the Cuda manager trap routine. It waits for Cuda to be idle, sends
|
||
; the first byte of the command packet. If Cuda didn't abort, then it sets up
|
||
; globals for the IRQ handler, and if a completion routine was specified, it returns
|
||
; back to the caller. If no completion routine, then it waits synchronously for
|
||
; the command/response to finish, using the busy bit. When the IRQ handler has finished
|
||
; the response packet, it preps the globals to expect an auto-response packet
|
||
; (ticks or ADB), clears 'busy' and calls the completion routine (if any).
|
||
;
|
||
; Inputs: a0 - pointer to parameter block as followsÉ
|
||
;
|
||
; pbPacketType dc.b
|
||
; pbCmd dc.b
|
||
; pbParam dc.b
|
||
; dc.b
|
||
; dc.b
|
||
; dc.b
|
||
; pbByteCnt dc.w
|
||
; pbBufPtr dc.l
|
||
; pbFlags dc.b
|
||
; dc.b
|
||
; pbResult dc.w
|
||
; pbCompletion dc.l
|
||
;
|
||
; Outputs: d0 - result (0 for now)
|
||
;
|
||
; Destroys: a0-a2, d0-d1
|
||
;________________________________________________________________________________________________
|
||
|
||
CudaDispatch
|
||
jsr CheckCudaPacket ; Validate the Packet type & command byte
|
||
tst.w pbResult(a0) ; is packet ok?
|
||
bne @done ; Exit if Error packet
|
||
movea.l EgretBase,a2 ; a2 gets ptr to globals
|
||
movea.l VIA,a1 ; a1 points to VIA base
|
||
|
||
cmpi.b #specialPkt,pbCmdType(a0) ; is this a special command?
|
||
|
||
bne.s @ckPDMInit ; check for Eclipse PowerDown Message Initialization
|
||
move.l a0,ADBpb(a2) ; yes, is to set the ADB param block (for autopoll data).
|
||
bra @done
|
||
@ckPDMInit
|
||
cmpi.b #PDMVectPkt,pbCmdType(a0) ; check for PowerDown message vector Init
|
||
bne.s @ckContInit
|
||
move.l pbParam(a0),PDMComp(a2) ; handler for Eclipse PowerDown Message Packet
|
||
bra @done
|
||
@ckContInit
|
||
cmpi.b #ContinueVectPkt,pbCmdType(a0) ; check for PowerDown message vector Init
|
||
bne.s @ckDoCont
|
||
move.l pbParam(a0),ContinueComp(a2) ; handler for power message continue procedure
|
||
bra @done
|
||
@ckDoCont
|
||
cmpi.b #DoContinueProc,pbCmdType(a0) ; check for PowerDown message vector Init
|
||
bne.s @CudaRestart ; Must be Egret Command
|
||
tst.l ContinueComp(a2) ; is there a continue procedure?
|
||
beq @done ; no, then do nothing
|
||
lea ContinueComp(a2),a2
|
||
move.l (a2),a2
|
||
jsr (a2) ; else, execute the continue procedure
|
||
bra @done
|
||
|
||
@CudaRestart
|
||
CmpI #$10C, (A0)
|
||
BEQ.B @L4
|
||
CmpI #$107, (A0)
|
||
BNE.B @endChicanery
|
||
Tst.B $64(A2)
|
||
BEQ @endChicanery
|
||
|
||
@L4 CmpI #$100, $2(A0)
|
||
BLT.B @L5
|
||
Move #$FFCE, $E(A0)
|
||
Bra @done
|
||
|
||
@L5 Lea.L $66(A2), A2
|
||
Move $6(A0), D1
|
||
BEQ @L9
|
||
SubQ #$1, D1
|
||
MoveQ.L #$0, D2
|
||
Move $2(A0), D2
|
||
MoveA.L $8(A0), A1
|
||
|
||
@L6 CmpI.B #$7, $1(A0)
|
||
BEQ.B @L7
|
||
Move.B (A1)+, $0(A2,D2.W)
|
||
Bra.B @L8
|
||
|
||
@L7 Move.B $0(A2,D2.W), (A1)+
|
||
|
||
@L8 AddQ #$1, D2
|
||
AndI #$FF, D2
|
||
DBF D1, @L6
|
||
|
||
@L9 MoveA.L ($DE0), A2
|
||
MoveA.L ($1D4), A1
|
||
CmpI.B #$C, $1(A0)
|
||
BEQ.B @endChicanery
|
||
Tst.L $10(A0)
|
||
BEQ @done
|
||
MoveA.L $10(A0), A1
|
||
Jsr (A1)
|
||
Bra @done
|
||
|
||
@endChicanery
|
||
move.w sr,-(sp) ; save SR
|
||
ori.w #hiIntMask,sr ; mask interrupts
|
||
|
||
eieioSTP
|
||
btst.b #TReq,vBufB(a1) ; does Cuda want to abort?
|
||
eieioSTP
|
||
beq.s @abort ; yes, wait for it to go away
|
||
btst.b #busy,flags(a2) ; has an idle acknowledge occured?
|
||
bne.s @abort ; no, then wait for it!
|
||
bset.b #busy,flags(a2) ; not an abort, mark that we're busy.
|
||
beq.s @sendPackType ; we were not busy before, so try to send the first byte
|
||
|
||
@abort move.w (sp)+,sr ; we were busy, enable interrupts
|
||
jsr pollByte ; poll shift reg, calling handler if interrupts masked
|
||
bra.s @endChicanery ; and keep waiting for busy to go away...
|
||
|
||
@sendPackType ; interrupts masked here
|
||
eieioSTP
|
||
bset.b #SRdir,vACR(a1) ; switch to output, Define direction FROM System
|
||
nop
|
||
eieioSTP
|
||
move.b pbCmdType(a0),vSR(a1) ; send command packet to shift reg
|
||
nop
|
||
eieioSTP
|
||
bset.b #vByteAck,vBufB(a1) ; make sure state is idle before transaction
|
||
nop
|
||
eieioSTP
|
||
bclr.b #TIP,vBufB(a1) ; assert TIP (we're starting command packet)
|
||
nop
|
||
eieioSTP
|
||
|
||
;
|
||
; If PollProc exists, Poll the SCC and save any available data
|
||
; When the shift register irq comes in call the PollProc
|
||
; then process the shift register irq data
|
||
;
|
||
movem.l d0-d3/a0-a4/a6,-(sp) ; save some registers
|
||
move.l PollStack,-(sp) ; save previous poll stack
|
||
lea @zero, a3
|
||
move.l sp,PollStack ; Pointer to buffer for polled bytes
|
||
|
||
; btst.b #0,SccIopFlag ; Check if we are in IOP mode (On Eclipse...)
|
||
; beq.s @wait
|
||
|
||
tst.l PollProc ; Check for a Poll Proc available
|
||
beq.s @wait ;
|
||
|
||
movea.l SccRd,a3 ; SCC may have data to get
|
||
movea.l a3,a6
|
||
addq.l #Actl,a3 ; Point to data available register (RR0)
|
||
addq.l #AData,a6 ; Point to the SCC data register
|
||
|
||
@wait btst.b #RxCa,(a3) ; Test for SCC data available
|
||
beq.s @2
|
||
move.b (a6),-(sp) ; Push the data on the stack
|
||
@2
|
||
bsr.l otherDelay
|
||
eieioSTP
|
||
btst.b #vShift,vIFR(a1) ; now wait for shift reg IRQ
|
||
eieioSTP
|
||
beq.s @wait
|
||
|
||
cmpa.l PollStack,SP ; Is there any poll data
|
||
beq.s @NoSCCData
|
||
;
|
||
; We have SCC data and a Poll Proc to call. Go call it
|
||
;
|
||
pea @NoSCCData ; Return addr for PollProc
|
||
move.l PollProc,-(SP) ; Point to the PollProc
|
||
rts ; Call the PollProc
|
||
|
||
@zero dc.w 0
|
||
|
||
@NoSCCData
|
||
move.l (sp)+,PollStack ; restore previous poll stack
|
||
movem.l (sp)+,d0-d3/a0-a4/a6 ; restore work registers
|
||
eieioSTP
|
||
btst.b #TReq,vBufB(a1) ; did CUDA abort?
|
||
eieioSTP
|
||
bne.s @accepted ; no, then it will accept our packet
|
||
;-----------------------------------------------------------------------------------------------
|
||
; Note that changing the VIA mode can generate an edge internal to the VIA which will
|
||
; increment the bit count for the next byte to be shifted.
|
||
; When outputing from the VIA to Cuda, the interrupt will occur prior to the rising edge
|
||
; of CB1. Delay long enough for the edge to occur before acknowledging the shift
|
||
; register interrupt. (R. Montagne 1/11/93)
|
||
;________________________________________________________________________________________________
|
||
move $d00,d0
|
||
divu #$50,d0
|
||
@mode7delay
|
||
dbra d0,@mode7delay
|
||
|
||
eieioSTP
|
||
bclr.b #SRdir,vACR(a1) ; yes, switch back to input
|
||
nop
|
||
eieioSTP
|
||
tst.b vSR(a1) ; clear pending shift register interrupt
|
||
nop
|
||
eieioSTP
|
||
ori.b #((1<<TIP)|\ ; abort the current transaction
|
||
(1<<vByteAck)),vBufB(a1) ;
|
||
nop
|
||
eieioSTP
|
||
@abortAck
|
||
bsr.l otherDelay
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a1) ; now wait for shift reg IRQ to acknowledge abort
|
||
eieioSTP
|
||
beq.s @abortAck ;
|
||
jsr CudaCallShiftRegIRQ ; handle it
|
||
bra.s @abort ; and wait
|
||
@accepted ; we sent the packetType, now set up for the IRQ handler
|
||
jsr SetTransferParams ; setup globals for this packet
|
||
jsr CudaCallShiftRegIRQ ; transfer second byte (command) to start things
|
||
move.w (sp)+,sr ; now enable interrupts
|
||
|
||
tst.l pbCompletion(a0) ; do we have a completion routine
|
||
bne.s @done ; yes, then return asynchronously
|
||
|
||
@waitComplete
|
||
btst.b #busy,flags(a2) ; otherwise, are we still busy?
|
||
beq.s @done ; no, then we're done...
|
||
|
||
jsr pollByte ; yes, poll out a byte if necessary
|
||
bra.s @waitComplete ; and wait here (synchronously)
|
||
|
||
@done moveq #0,d0 ; no errors for now
|
||
rts
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: PollByte 914e
|
||
;
|
||
; Function: This routine checks to see if level 1 interrupts are masked, exits if not.
|
||
; If masked, it polls the flag register for a shift reg interrupt, and
|
||
; calls the handler if found.
|
||
;
|
||
; Inputs: a1 - VIA base ptr
|
||
; a2 - globals pointer
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Destroys: d0,d1
|
||
;________________________________________________________________________________________________
|
||
; Export PollByte
|
||
PollByte
|
||
move.w sr,d0 ; get 68xxx interrupt mask
|
||
andi.w #hiIntMask,d0 ; are we at interrupt level?
|
||
beq.s @exit ; no, just exit
|
||
bsr.l otherDelay
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a1) ; yes, poll the shift reg
|
||
eieioSTP
|
||
beq.s @exit ; no shift reg interrupt, return
|
||
bsr.s CudaCallShiftRegIRQ ; yes, handle it
|
||
@exit rts
|
||
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: SendByte 9168
|
||
;
|
||
; Function: This routine transmits a byte by writing to the via shift register and
|
||
; then changes the state of vByteAck to indicate that the via shift register
|
||
; contains data ready to be read.
|
||
;
|
||
; Inputs: d0 - byte to send
|
||
; a1 - VIA base ptr
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Destroys: d1
|
||
;________________________________________________________________________________________________
|
||
; Export SendByte
|
||
SendByte
|
||
eieioSTP
|
||
move.b d0,vSR(a1) ; send the byte to the shift reg
|
||
nop
|
||
eieioSTP
|
||
eori.b #1<<vByteAck,vBufB(a1) ; let Cuda know it's there
|
||
nop
|
||
eieioSTP
|
||
rts
|
||
|
||
;________________________________________________________________________________________________
|
||
Export CudaCallShiftRegIRQ
|
||
CudaCallShiftRegIRQ
|
||
movem.l a0-a3/d0-d3, -(sp) ; save regs like interrupt handler does
|
||
move.w sr, -(sp) ; save status reg
|
||
movea.l Lvl1DT+8,a0 ; get the shift reg IRQ handler
|
||
jsr (a0) ; call it
|
||
move.w (sp)+, sr ; restore status reg
|
||
movem.l (sp)+, a0-a3/d0-d3 ; restore regs
|
||
rts
|
||
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: CudaShiftRegIRQ 9176
|
||
;
|
||
; Function: This routine is called in response to a VIA shift reg interrupt. It will transfer
|
||
; the next byte in the current packet. When the packet is complete, the globals are
|
||
; prepped for an auto-response packet (ADB/Ticks), then the completion routine
|
||
; is called (if present).
|
||
;
|
||
; Cuda Transaction States -
|
||
; ___ ____
|
||
; ViaDir TIP vByteAck TReq
|
||
; 0 0 0 0 Receive Data Byte
|
||
; 0 0 0 1 Receive Last Data Byte
|
||
; 0 0 1 0 Receive Data Byte
|
||
; 0 0 1 1 Receive Last Data Byte
|
||
; 0 1 0 0 Abort/Sync
|
||
; 0 1 0 1 Abort/Sync
|
||
; 0 1 1 0 Attention
|
||
; 0 1 1 1 Idle
|
||
; 1 0 0 0 illegal
|
||
; 1 0 0 1 Transmit Data Byte
|
||
; 1 0 1 0 illegal
|
||
; 1 0 1 1 Transmit Data Byte
|
||
; 1 1 0 0 Abort/Sync
|
||
; 1 1 0 1 Abort/Sync
|
||
; 1 1 1 0 illegal
|
||
; 1 1 1 1 Idle
|
||
;
|
||
; Inputs: a1 - VIA base ptr
|
||
;
|
||
; Outputs: a2 - globals pointer
|
||
;
|
||
; Destroys: a0-a2,d0-d3
|
||
;________________________________________________________________________________________________
|
||
CudaShiftRegIRQ
|
||
move.w sr,d3
|
||
ori.w #hiIntMask,sr ; mask interrupts <LW8><LW5>
|
||
|
||
btst.b #vShift,vIFR(a1)
|
||
bne.s @output
|
||
|
||
move.w d3,sr ; restore interrupts
|
||
rts
|
||
|
||
;________________________________________________________________________________________________
|
||
; When outputing from the VIA to Cuda, the interrupt will occur prior to the rising edge
|
||
; of CB1. Delay long enough for the edge to occur before acknowledging the shift
|
||
; register interrupt. (R. Montagne 1/11/93)
|
||
;________________________________________________________________________________________________
|
||
|
||
@output
|
||
movea.l EgretBase,a2 ; get ptr to globals <13>
|
||
bset.b #busy,flags(a2) ; make sure we're marked as busy
|
||
|
||
btst.b #$4, $1600(A1)
|
||
beq.s * + $60 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
move $d00,d0
|
||
divu #$50,d0
|
||
@mode7delay
|
||
dbra d0,@mode7delay ; <LW2><VIA rbm>
|
||
|
||
eieioSTP
|
||
tst.b vSR(a1) ; clear the shift reg interrupt
|
||
nop
|
||
eieioSTP
|
||
tst.w sendHdrCnt(a2) ; any bytes left in header?
|
||
ble.s @ckSendData ; no, see if any send bytes left...
|
||
|
||
movea.l sendHdrPtr(a2),a0 ; get ptr to header
|
||
move.b (a0)+,d0 ; get next header byte
|
||
move.l a0,sendHdrPtr(a2) ; and update header ptr
|
||
bsr SendByte ; send the byte
|
||
subq.w #1,sendHdrCnt(a2) ; count it
|
||
bra @exit ; and exit
|
||
@ckSendData
|
||
tst.w sendDataCnt(a2) ; any bytes left in data to send
|
||
ble.s @CmdFinished ; no, then we're finished with command packet
|
||
movea.l sendDataPtr(a2),a0 ; get current data ptr
|
||
move.b (a0)+,d0 ; yes, get next data byte
|
||
move.l a0,sendDataPtr(a2) ; and update the ptr
|
||
bsr SendByte ; send it
|
||
subq.w #1,sendDataCnt(a2) ; count it
|
||
bra @exit ; and exit
|
||
@CmdFinished
|
||
eieioSTP
|
||
bclr.b #SRdir,vACR(a1) ; now switch to input
|
||
nop
|
||
eieioSTP
|
||
;________________________________________________________________________________________________
|
||
; When changing VIA direction, a clock can be generated to the VIA bit counter. An
|
||
; access to the shift data register will keep the counter in sync with the communications
|
||
; protocol to Cuda.
|
||
;________________________________________________________________________________________________
|
||
eieioSTP
|
||
tst.b vSR(a1) ; make sure VIA counter is in sync <LW2><VIA rbm>
|
||
eieioSTP
|
||
@sendCmd
|
||
eieioSTP
|
||
ori.b #((1<<TIP)| \ ; terminate transaction
|
||
(1<<vByteAck)),vBufB(a1) ; and set idle state
|
||
nop
|
||
eieioSTP
|
||
bra @exit ; and exit
|
||
|
||
@input ;-----------------------------------------------------------------------------
|
||
eieioSTP
|
||
move.b vSR(a1),d0 ; read the byte from shift reg into D0
|
||
nop
|
||
eieioSTP
|
||
tst.w rcvHdrCnt(a2) ; any bytes left in response packet header?
|
||
ble.s @ckRcvData ; if not then must be data byte
|
||
@getHdrByte
|
||
|
||
move.w rcvHdrIndex(a2),d1 ; get index into header
|
||
lea rcvHeader(a2),a0 ; point to header buffer
|
||
move.b d0,(a0,d1.w) ; store byte away
|
||
|
||
addq.w #1,rcvHdrIndex(a2) ; bump to next byte
|
||
subq.w #1,rcvHdrCnt(a2) ; count it
|
||
|
||
tst.w rcvHdrCnt(a2) ; chk header count
|
||
bgt.s @ackHdr ; not done with header yet... exit
|
||
;
|
||
; If we have an error packet in progres then read 5 bytes instead of 4 for the header.
|
||
; A flag will be set on the fourth byte of an error packet and will be cleared
|
||
; after reading the fifth byte of the error packet.
|
||
;
|
||
@CheckError lea rcvHeader(a2),a0 ; point to header buffer
|
||
cmp.b #ErrorPkt,1(a0) ; check packet type for error packet
|
||
bne.s @ackHdr ; not an error packet go check for data
|
||
|
||
bclr.b #BadPkt,flags(a2) ; check for error packet in progress flag
|
||
bne.s @ackHdr ; we read the fifth byte of the error packet
|
||
@readbyte5 addq.w #1,rcvHdrCnt(a2) ; adjust the count before reading the fifth byte
|
||
bset.b #BadPkt,flags(a2) ; set the flag then read the fifth byte
|
||
bra.s @ackHdr
|
||
|
||
@ckRcvData
|
||
btst.b #TIP,vBufB(a1) ; is a transaction in progress?
|
||
bne.w @done ; no, don't buffer the idle acknowledge interrupt
|
||
tst.w rcvDataCnt(a2) ; is request for zero bytes?? <SM5>
|
||
movea.l rcvDataPtr(a2),a0 ; get ptr to receive data buffer
|
||
beq.s @zeroReq ; yes, don't pass any data back <SM5>
|
||
move.b d0,(a0)+ ; store the data byte
|
||
@zeroReq
|
||
eieioSTP
|
||
btst.b #TREQ,vBufB(a1) ; was this the last byte?
|
||
eieioSTP
|
||
bne @lastIrq ; yes, terminate response packet
|
||
move.l a0,rcvDataPtr(a2) ; and update data ptr
|
||
subq.w #1,rcvDataCnt(a2) ; count it
|
||
bgt.s @ack ; not last, normal acknowlege
|
||
btst.b #openData,flags(a2) ; is this an open ended data packet?
|
||
bne.s @lastIrq ; and we're done
|
||
|
||
@ack
|
||
tst.w rcvDataCnt(a2) ; any receive data bytes to get?
|
||
ble @lastIrq ; no, then terminate transaction and exit
|
||
@ackHdr
|
||
move.b vBufB(a1),d0 ; get current handshake state
|
||
andi.b #((1<<TIP)|\
|
||
(1<<vByteAck)|\
|
||
(1<<TReq)),d0
|
||
cmp.b #((1<<TIP)|\ ; is this an idle acknowledge?
|
||
(1<<vByteAck)|\
|
||
(1<<TReq)),d0
|
||
beq @done ; yes, dont handshake.
|
||
|
||
cmp.b #((1<<TIP)|\ ; is this an attention byte?
|
||
(1<<vByteAck)|\
|
||
(0<<TReq)),d0
|
||
beq.s @attnIrq ; yes
|
||
|
||
andi.b #((1<<TIP)|\ ; now look at TIP and TReq...
|
||
(0<<vByteAck)|\
|
||
(1<<TReq)),d0
|
||
cmp.b #((0<<TIP)|\ ; is this the last byte?
|
||
(1<<TReq)),d0 ;
|
||
beq.s @lastIRQ ; yes
|
||
|
||
@dataIrq
|
||
eieioSTP
|
||
eori.b #1<<vByteAck,vBufB(a1) ; acknowledge the current byte
|
||
nop
|
||
eieioSTP
|
||
bra @exit ;
|
||
|
||
@attnIrq
|
||
eieioSTP
|
||
bclr.b #TIP,vBufB(a1) ; start the response packet transaction
|
||
nop
|
||
eieioSTP
|
||
bra @exit ;
|
||
|
||
@lastIrq
|
||
eieioSTP
|
||
ori.b #((1<<TIP)|\ ; no, terminate the response packet transaction
|
||
(1<<vByteAck)),vBufB(a1)
|
||
nop
|
||
eieioSTP
|
||
|
||
;---------------------------------------------------------------------------
|
||
|
||
; <SM6> (rbm)
|
||
; Now that the response transaction has been terminated, let's wait for the idle <SM6> (rbm)
|
||
; acknowledge interrupt to occur. This should happen about 71.5 µS after the negation <SM6> (rbm)
|
||
; of TIP. This will prevent any problem related to interrupts being masked during the <SM6> (rbm)
|
||
; transmission of the idle acknowledge when another asynchronous Cuda transaction is to <SM6> (rbm)
|
||
; begin while interrupts are masked (as may happen during disc access while moving the <SM6> (rbm)
|
||
; mouse). <SM6> (rbm)
|
||
; <SM6> (rbm)
|
||
@waitIdleAck ; <SM6> (rbm)
|
||
eieioSTP
|
||
bsr.l otherDelay
|
||
btst.b #ifSR,vIFR(a1) ; wait for idle state acknowledgement <SM6> (rbm)
|
||
eieioSTP
|
||
beq.s @waitIdleAck ; <SM6> (rbm)
|
||
eieioSTP
|
||
tst.b vSR(a1) ; clear the shift reg interrupt <SM6> (rbm)
|
||
nop
|
||
eieioSTP
|
||
|
||
;---------------------------------------------------------------------------
|
||
@done
|
||
movea.l curPb(a2),a0 ; a0 points to current param block
|
||
lea rcvHeader(a2),a1 ; a1 points to header buffer
|
||
eieioSTP
|
||
cmp.b #ErrorPkt,1(a1) ; check for Error response packet
|
||
eieioSTP
|
||
bne.s @NotError
|
||
;
|
||
; The current transaction generated an Error <11>
|
||
;
|
||
move.l 1(a1),pbParam(a0) ; Return the Error Response packet to the caller (dont include attn byte)
|
||
move.w #paramErr,pbResult(a0) ; and return a parameter block error
|
||
|
||
@NotError cmpa.l adbPb(a2),a0 ; was this an implicit command?
|
||
beq.s @implicit ; yes, handle autopoll/tick packet
|
||
|
||
tst.b 1(a1) ; is this an ADB response?
|
||
bne.s @ckComp ; no, then data already transfered, call completion
|
||
|
||
@adbResp
|
||
cmpa.l adbPb(a2),a0 ; is this autopoll data
|
||
bne.s @skip ; no, don't fix ray's flag
|
||
bset.b #EgAutoPoll,2(a1) ; yes, fix em
|
||
@skip
|
||
|
||
btst.b #EgAutoPoll,2(a1) ; check status, is this AutoPoll data?
|
||
bne @ckAutoPollComp ; yes, handle if we have completion routine
|
||
|
||
move.b 2(a1),pbFlags(a0) ; explicit ADB command, stuff flags byte
|
||
move.w rcvHdrIndex(a2),d0 ; get header+data byte count
|
||
subq.w #4,d0 ; - header bytes
|
||
beq.s @dontupdate ; if no data received don't update the byte count
|
||
move.w d0,pbByteCnt(a0) ; stuff data byte count
|
||
@dontupdate move.l pbBufPtr(a0),a2 ; get users buffer ptr
|
||
addq.w #4,a1 ; point at the data
|
||
bra.s @cnt
|
||
@xfer move.b (a1)+,(a2)+ ; copy the byte
|
||
@cnt dbra d0,@xfer ; repeat for all bytes
|
||
|
||
move.l EgretBase,a2 ; get globals ptr again
|
||
|
||
@ckComp move.l pbCompletion(a0),d0 ; any completion routine?
|
||
beq @exitNoComp ; no, just exit
|
||
|
||
move.l d0,a1 ; yes, get it's address
|
||
move.l a0,-(sp) ; save param block ptr
|
||
bigjsr SetResponseParams,a3 ; setup globals to handle auto response packets again
|
||
move.w d3,sr ; restore interrupts
|
||
move.l (sp)+,a0 ; restore param block ptr
|
||
move.w sr,-(sp) ; save register for completion routines that trash it <SM7>
|
||
jsr (a1) ; and call it <SM7>
|
||
move.w (sp)+,sr ; <SM7>
|
||
rts ; <SM7>
|
||
|
||
|
||
;--------------------------------------------------------------------------------------------
|
||
; AutoPoll or Tick data, push it on stack and call completion rtn
|
||
|
||
@implicit
|
||
tst.b RespPktType(a1) ; is this an ADB response?
|
||
beq.s @ckAutoPollComp ; yes, handle it
|
||
|
||
cmpi.b #tickPkt,RespPktType(a1) ; is this a short tick response?
|
||
beq.s @ckTickComp ; yes, handle it (has no param block)
|
||
cmpi.b #pseudoPkt,RespPktType(a1) ; no, should be pseudo command tick response
|
||
; ShiftRegIRQPatch from EgretPatchesToo.a
|
||
bne.s @ckPDM ; check for PowerDown Message (Eclipse ONLY)
|
||
cmpi.b #RdTime,RespCmd(a1) ; yes, it should be read time
|
||
bne.s @exitNoComp ; if not read time ignore the transaction (SHOULD NOT HAPPEN!!)
|
||
bra.s @ckTickComp ; otherwise, push response packet on stack, call it.
|
||
; >>CONTINUE original routine
|
||
;-----------------------------------------------
|
||
; Eclipse Check for PowerDown Message
|
||
;
|
||
@ckPDM cmpi.b #PDMPkt,RespPktType(a1) ; check for PowerDown Message Packet type <GAA Eclipse>
|
||
bne.s @exitNoComp ; None of the above Packets ignore it (SHOULD NOT HAPPEN)
|
||
; if it does EGRET is Very SICK!! <P4>
|
||
;
|
||
; For PDM packets check for service routine address and
|
||
; call it if one exists.
|
||
;
|
||
move.l PDMComp(a2),d2 ; get the completion routine address
|
||
beq.s @exitNoComp ; go away if vector is null <P4>
|
||
bigjsr SetResponseParams,a3 ; setup globals to handle auto response packets again
|
||
move.l d2,a3 ; call the Service routine
|
||
move.b RespCmd(a1),d0 ; get the powerDown Switch destination position
|
||
move.w sr,d3 ; save interrupts
|
||
jsr (a3)
|
||
move.w d3,sr ; restore interrupts
|
||
bra.s @exit ; done, now exit
|
||
; end ShiftRegIRQPatch EgretPatchesToo.a <P4>
|
||
@ckTickComp ; tick data, check for completion routine
|
||
move.l tickComp(a2),d2 ; get completion routine in d2
|
||
beq.s @exitNoComp ; none specified, just exit
|
||
bra.s @push ; otherwise, push response packet on stack, call it.
|
||
|
||
@ckAutoPollComp ; ADB autopoll data, check for completion rtn
|
||
bset.b #EgAutoPoll,2(a1) ; Set AutoPoll bit to fix bug in old Egret parts
|
||
tst.l a0 ; do we really have a current param block? (we should)
|
||
beq.s @exitNoComp ; no, exit
|
||
|
||
move.l pbCompletion(a0),d2 ; any completion routine? (keep in d2)
|
||
beq.s @exitNoComp ; no, just exit
|
||
@push
|
||
suba.w #12,sp ; allocate 12 byte buffer on stack
|
||
movea.l sp,a2 ; point to the buffer
|
||
move.l (a1)+,(a2)+ ; copy response header onto stack
|
||
move.l (a1)+,(a2)+ ; copy response data onto stack
|
||
move.l (a1)+,(a2)+ ; copy response data onto stack
|
||
movea.l EgretBase,a2 ; restore ptr to globals
|
||
move.w rcvHdrIndex(a2),d0 ; d0 = # bytes in response header
|
||
subq.w #4,d0 ; byte count = # data bytes (strip off header bytes)
|
||
bigjsr SetResponseParams,a3 ; setup globals to handle auto response packets again
|
||
move.w d3,sr ; restore interrupts
|
||
|
||
move.l sp,a1 ; a1 = ptr to response packet
|
||
addq.l #2,a1 ; a1 = ptr to status flag
|
||
move.l d2,a3 ; get completion routine
|
||
|
||
;
|
||
; ¥¥¥¥¥ Calling Completion Routine ¥¥¥¥¥
|
||
;
|
||
; a0 = Pointer to parameter block
|
||
; a1 = Pointer to status flag in response packet (Cuda Transaction Format)
|
||
; a2 = Pointer to Cuda Globals
|
||
; d0 = Number of bytes in response packet, excluding Attention, Type, Flags & Command.
|
||
;
|
||
move.w d3, -(sp) ; preserve status reg during completion routine {8}<gjs>
|
||
jsr (a3) ; call it (a0 points to param block for ADB)
|
||
move.w (sp)+, d3 ; restore status reg
|
||
adda.w #12,sp ; pop buffer
|
||
rts
|
||
|
||
@exitNoComp ; no completion routine specified,
|
||
bigjsr SetResponseParams,a3 ; setup globals to handle auto response packets again
|
||
@exit ;
|
||
move.w d3,sr ; restore interrupts
|
||
rts
|
||
|
||
Eject
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: SetTransferParams 93e0
|
||
;
|
||
; Function: This routine sets up transmit/receive ptrs (globals) for the packet pointed to by A0,
|
||
; for use by the Shift Reg interrupt handler.
|
||
;
|
||
; Inputs: a0 - Param block pointer
|
||
; a1 - VIA
|
||
; a2 - Ptr to globals (EgretBase)
|
||
;
|
||
; Outputs: none
|
||
; Destroys: d0,d1
|
||
;________________________________________________________________________________________________
|
||
; Export SetTransferParams
|
||
SetTransferParams
|
||
move.l a1,-(sp) ; save a1
|
||
lea pbCmd(a0),a1
|
||
move.l a1,sendHdrPtr(a2) ; point to 1st byte of header to send
|
||
|
||
moveq #0,d0
|
||
move.b pbCmd(a0),d0 ; get command
|
||
|
||
tst.b pbCmdType(a0) ; is this an ADB command?
|
||
bne.s @pseudo ; no, must be a pseudo command
|
||
|
||
andi.b #%00001111,d0 ; keep low 4 bits
|
||
biglea ADBCntTable,a1 ; get ptr to our ADB command table
|
||
bra @check ; and look up our send/rcv byte counts
|
||
|
||
;
|
||
; Pseudo Command. Now Check for SEND DFAC and treat as special case if it is. <12>
|
||
; On DFAC, use the byte count in the parameter block as the count to send <12>
|
||
; to Egret instead the count contained in the PseudoCntTable. <12>
|
||
;
|
||
@pseudo
|
||
cmp.b #WrDFAC,pbCmd(a0) ; check for DFAC <12>
|
||
bne.s @notDFAC ; use the table if not DFAC <12>
|
||
|
||
move.w pbByteCnt(a0),d1 ; was Write DFAC use the byte count in the pBlock <12>
|
||
addq.w #1,d1 ; include the packet byte already sent <12>
|
||
move.w d1,sendHdrCnt(a2) ; set up header byte count <12>
|
||
clr.w sendDataCnt(a2) ; no extended data bytes <12>
|
||
clr.l sendDataPtr(a2) ; no extended data ptr <12>
|
||
bra @rcvParams
|
||
|
||
@notDFAC cmp.b #$25,pbCmd(a0)
|
||
beq @dontjump
|
||
cmp.b #RdWrIIC,pbCmd(a0) ; check for IIC transaction <SM3>
|
||
bne.s @notRdWrIIC ; use the table if not RdWrIIC <SM3>
|
||
*
|
||
* Here is how the transfer globals are set up for IIC transactionsÉ
|
||
*
|
||
* _Parameter______ _RdWrIIC_(write)_____________ _Parameter______ _RdWrIIC_(read)______________
|
||
* CudaPB CudaPB
|
||
* pbCmdType pseudoPkt pbCmdType pseudoPkt
|
||
* pbCmd RdWrIIC pbCmd RdWrIIC
|
||
* pbParam[0] IIC Device Addr. pbParam[0] IIC Device Addr.
|
||
* pbParam[1] IIC Register Addr. (optional) pbParam[1] IIC Register Addr. (optional)
|
||
* pbParam[2] ¥ pbParam[2] ¥
|
||
* pbParam[3] ¥ pbParam[3] ¥
|
||
* pbByteCnt # fields in pbParam array pbByteCnt # fields in pbParam array
|
||
* pbBufPtr myBuffer pbBufPtr myBuffer
|
||
* pbFlags ¥ pbFlags ¥
|
||
* pbSpare ¥ pbSpare ¥
|
||
* pbResult ¥ pbResult ¥
|
||
* pbCompletion NIL pbCompletion NIL
|
||
* SendHdrCnt CudaPB.pbByteCnt SendHdrCnt CudaPB.pbByteCnt
|
||
* SendHdrPtr &CudaPB.pbCmd SendHdrPtr &CudaPB.pbCmd
|
||
* SendDataCnt (char)myBuffer[0] SendDataCnt 0
|
||
* SendDataPtr &myBuffer[1] SendDataPtr NIL
|
||
* RcvHdrCnt 4+0 RcvHdrCnt 4+0
|
||
* RcvHdrIndex 0 RcvHdrIndex 0
|
||
* RcvDataCnt 0 RcvDataCnt (char)myBuffer[0]
|
||
* RcvDataPtr &myBuffer[1] RcvDataPtr &myBuffer[1]
|
||
* RcvHeader RcvHeader
|
||
* RespAttn ¥ RespAttn ¥
|
||
* RespType ¥ RespType ¥
|
||
* RespFlags ¥ RespFlags ¥
|
||
* RespCmd ¥ RespCmd ¥
|
||
* RespData ¥ RespData ¥
|
||
* curPB CudaPB curPB CudaPB
|
||
*
|
||
@dontjump
|
||
move.w pbByteCnt(a0),d1 ; RdWrIIC uses byte count for send portion <SM3>
|
||
addq.w #1,d1 ; include the packet byte already sent <SM3>
|
||
move.w d1,sendHdrCnt(a2) ; set up header byte count <SM3>
|
||
move.w #4,rcvHdrCnt(a2) ; 4 byte header default <SM3>
|
||
clr.w rcvHdrIndex(a2) ; reset index into header buffer <SM3>
|
||
move.l pbBufPtr(a0),a1 ; get address of data buffer <SM3>
|
||
|
||
cmp.b #RdWrIIC,pbCmd(a0)
|
||
beq.s @doIICwrite
|
||
|
||
btst.b #0,4(a0)
|
||
bne.s @doIICread
|
||
@doIICwrite ; <SM3>
|
||
btst.b #0,pbParam(a0)
|
||
bne.s @doIICread
|
||
|
||
moveq #0,d1 ; data phase count must be 1 to 256 <SM3>
|
||
move.b (a1),d1 ; <SM3>
|
||
bne.s @wrCntOK ; <SM3>
|
||
move.w #$0100,d1 ; <SM3>
|
||
@wrCntOK ; <SM3>
|
||
move.w d1,sendDataCnt(a2) ; number of extended data bytes to send <SM3>
|
||
@newlbl
|
||
adda.l #1,a1 ; <SM3>
|
||
move.l a1,sendDataPtr(a2) ; extended data ptr <SM3>
|
||
clr.w rcvDataCnt(a2) ; no data to receive on IIC write <SM3>
|
||
move.l a1,rcvDataPtr(a2) ; but let's point at xmit buffer to be safe <SM3>
|
||
bra.s @RdWrIICexit ; <SM3>
|
||
@doIICread ; <SM3>
|
||
clr.w sendDataCnt(a2) ; no extended data bytes to send <SM3>
|
||
clr.l sendDataPtr(a2) ; no extended data ptr <SM3>
|
||
moveq #0,d1 ; data phase count must be 1 to 256 <SM3>
|
||
move.b (a1),d1 ; <SM3>
|
||
bne.s @rdCntOK ; <SM3>
|
||
move.w #$0100,d1 ; <SM3>
|
||
@rdCntOK ; <SM3>
|
||
move.w d1,rcvDataCnt(a2) ; number of extended data bytes to receive <SM3>
|
||
adda.l #1,a1 ; <SM3>
|
||
move.l a1,rcvDataPtr(a2) ; extended data ptr <SM3>
|
||
@RdWrIICexit ; <SM3>
|
||
bset.b #openData,flags(a2) ; open ended data packet (RdWrIIC) <SM3>
|
||
bra.s @exit ; <SM3>
|
||
@notRdWrIIC ; <SM3>
|
||
biglea PseudoCntTable,a1 ; get ptr to our pseudo command table
|
||
@check
|
||
lsl.w #1,d0 ; x 2 for word table
|
||
move.w (a1,d0.w),d1 ; get send/rcv byte counts for this command
|
||
|
||
ror.w #8,d1 ; get send byte count in low byte
|
||
tst.b d1 ; is this an open-ended send command?
|
||
bmi.s @sendExt ; yes, branch...
|
||
move.b d1,d0 ; get byte count from table
|
||
ext.w d0 ; extend to word
|
||
addq.b #1,d0 ; data bytes + 1 = header byte count
|
||
move.w d0,sendHdrCnt(a2) ; set up header byte count
|
||
clr.w sendDataCnt(a2) ; no extended data bytes
|
||
clr.l sendDataPtr(a2) ; no extended data ptr
|
||
bra.s @rcvParams ; now setup receive ptrs
|
||
|
||
@sendExt moveq #$7F,d0 ; prepare to mask sign
|
||
and.w d1,d0 ; get rid of sign
|
||
addq.w #1,d0 ; + 1 for command (packet type already sent)
|
||
move.w d0,sendHdrCnt(a2) ; set up header byte count
|
||
move.w pbByteCnt(a0),sendDataCnt(a2) ; set up data byte count
|
||
move.l pbBufPtr(a0),sendDataPtr(a2) ; set up send data ptr
|
||
|
||
@rcvParams clr.w rcvHdrIndex(a2) ; reset index into header buffer
|
||
move.w #4,rcvHdrCnt(a2) ; 4 byte header default
|
||
asr.w #8,d1 ; get receive data byte count
|
||
bmi.s @rcvExt ; branch for open-ended reads
|
||
|
||
tst.b pbCmdType(a0) ; reading, is this a pseudo command?
|
||
beq.s @rcvADB ; no, must be adb data
|
||
|
||
lea pbParam(a0),a1 ; pseudo data will be received in pbParam
|
||
move.l a1,rcvDataPtr(a2)
|
||
move.w d1,rcvDataCnt(a2) ; get receive count from table
|
||
bra.s @exit ; and exit
|
||
|
||
@rcvADB add.w d1,rcvHdrCnt(a2) ; total header bytes = 4 + ADB data
|
||
clr.w rcvDataCnt(a2) ; not used
|
||
bclr.b #openData,flags(a2) ; this is not an open ended data packet (readPram, read6805)
|
||
bra.s @exit
|
||
|
||
@rcvExt move.w pbByteCnt(a0),rcvDataCnt(a2) ; set up received data byte count
|
||
move.l pbBufPtr(a0),rcvDataPtr(a2) ; set up received data buffer ptr
|
||
bset.b #openData,flags(a2) ; this is an open ended data packet (readPram, read6805)
|
||
|
||
@exit move.l a0,curPb(a2) ; set up current param block
|
||
movea.l (sp)+,a1 ; restore a1
|
||
rts
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: CheckPacketPatch
|
||
; a0 = pointer to parameter block
|
||
; Exit: z = 1 if packet type within bounds
|
||
; z 1 if packet type not within bounds
|
||
;_______________________________________________________________________
|
||
CheckCudaPacket
|
||
moveq #0,d0 ; pre clear the register <17>rbm
|
||
move.b pbCmdType(a0),d0 ; get the command byte <17>rbm
|
||
beq.s @okExit ; if it is an ADB command, continue <17>rbm
|
||
cmp.w #DoContinueProc,d0 ; is this one of the special packets? <17>rbm
|
||
blt.s @notSpecial ; no, error <17>rbm
|
||
@OkExit
|
||
move.w #0,pbResult(a0) ; no error returned in parameter block <17>rbm
|
||
rts ; <17>rbm
|
||
@notSpecial
|
||
cmp.w #pseudoPkt,d0 ; is it a standard packet <17>rbm
|
||
bne.s @BadExit ; yes, do it <17>rbm
|
||
cmp.b #MaxPseudoCmd,pbCmd(a0) ; is it a valid pseudo command? <17>rbm
|
||
bls.s @OkExit ; yes <17>rbm
|
||
move.w #InvPseudo,pbParam(a0) ; report a pseudo command error
|
||
bra.s @errorExit
|
||
@BadExit
|
||
move.w #InvPkt,pbParam(a0) ; report invalid packet type <17>rbm
|
||
@errorExit
|
||
move.w pbCmdType(a0),pbParam+2(a0) ; we are faking an error packet <17>rbm
|
||
move.w #paramErr,pbResult(a0) ; parameter error in result field <17>rbm
|
||
rts
|
||
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: CudaTickHandler 9566
|
||
;
|
||
; Function: This is the completion routine for tick response packets.
|
||
;
|
||
; Inputs: d0 - number of bytes in response packet
|
||
; a1 - pointer to status flag
|
||
; a2 - ptr to globals
|
||
; (sp) - points to response packet
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Destroys: ???
|
||
;
|
||
; This routine is from the Regatta Patches file PatchIIciROM.a
|
||
;----------------------------------------------------------------------------------------------------
|
||
; This patch fixes a bug in Egret Manager TickHandler routine. <89><101>
|
||
; The routine will store the 32 bit time passed by Egret to the
|
||
; system if the packet is a ReadRealTime into TIME lowmen.
|
||
; Decrements the lowmem Time by one to compensate for the interrupt
|
||
; Handler incrementing it by one and then calls the LVL1DT interrupt
|
||
; handler.
|
||
; If the packet is a tick packet then it calls LVL1DT to increment the
|
||
; time setting and check the alarm state.
|
||
;
|
||
; Entry:
|
||
; A1.l = Points at Response data buffer At Flags byte:
|
||
;
|
||
; +---------+----------+---------+---------+---------//-------+
|
||
; | Attn | Pkt Type | Flags | Pkt Cmd | 8 Bytes data Max |
|
||
; +---------+----------+---------+---------+---------//-------+
|
||
;
|
||
; A2.l = Points at Egret Manager Globals
|
||
;
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
;________________________________________________________________________________________________
|
||
|
||
CudaTickHandler
|
||
WITH respPacket,EgretGlobals ; {
|
||
|
||
subq.l #2,a1 ; point to the beginning of the Response data buffer
|
||
cmpi.b #TickPkt,RespType(a1) ; Check the Packet type
|
||
beq.s @CallLVL1DT ; If tick packet just call LVL1DT handler
|
||
;
|
||
; The packet was a readTime packet from Egret. Update the Time lowmem and
|
||
; adjust it to compensate for the increment in the LVL1DT handler.
|
||
;
|
||
move.l RespData(a1),Time ; write the new time in lowmem TIME
|
||
subq.l #1,Time ; adjust to compensate for increment in LVL1DT
|
||
;
|
||
; JUMP to routine pointed to by the Contents of LVL1DT
|
||
;
|
||
|
||
@CallLVL1DT
|
||
move.l VIA,a1 ; point to the VIA
|
||
move.l LVL1DT,a0 ; get vector
|
||
eieioSTP
|
||
jmp (a0)
|
||
eieioSTP
|
||
ENDWITH ; }
|
||
|
||
;=========================================================================
|
||
; Routine: CudaInit 9584
|
||
;
|
||
; This routine sends a NOP/WarmStart command to Cuda. This routine is
|
||
; called early during rom Startup to stop autopoll and 1 sec irq. Also,
|
||
; the routine will issue a Send DFAC command to Cuda to initialize the
|
||
; the DFAC hardware to a known state. The routine does not use ANY
|
||
; memory it is register driven only.
|
||
;
|
||
; Inputs: NONE
|
||
;
|
||
; Outputs: NONE
|
||
;
|
||
; Destroys: D0, D1, D2, D3, A1, A5, A6, A4 (Egret 2 implementation)
|
||
; Destroys: D0, D3, A2, A5, A6 (Egret 3 implementation)
|
||
;
|
||
; NOTE: This routine is called via a BSR6 and returns via a RTS6
|
||
;-------------------------------------------------------------------------
|
||
;
|
||
; The following sequence synchronizes Cuda to the system by disabling all asynchronous transaction
|
||
; sources (Auto Poll Data, RTC & Power Messages) and insures that no data (full or partial byte)
|
||
; is pending in the VIA data shift register. ByteAck is asserted with TIP negated. Cuda responds
|
||
; by asserting TReq and sends a byte to generate a VIA shift register interrupt. After the
|
||
; interrupt occurs, ByteAck is negated. Cuda responds by negating TReq and then delays 25µS prior
|
||
; to sending an idle acknowledge. The VIA shift register interrupt must be cleared within 25µS of
|
||
; the negation of TReq by Cuda. Once the idle acknowledge interrupt occurs, the VIA shift register
|
||
; interrupt is cleared and Cuda is ready to accept commands. No collisions should be possible
|
||
; until an asynchronous transaction source is enabled.
|
||
; ___________________________________________________________
|
||
; ___ |
|
||
; TIP __|........................................................
|
||
; _______ ___________________________
|
||
; | | |
|
||
; ByteAck __| |_______________________|
|
||
; ___________________________________________________________
|
||
; ________ |||||||| ||||||||
|
||
; ViaClk |||||||| ||||||||
|
||
; ___________________________________________________________
|
||
;
|
||
; ViaData ...........................................................
|
||
; _____ _______ ______
|
||
; | | sync | | idle |
|
||
; VIA_IRQ _____|_____________________| ack |___________| ack |____
|
||
; ___________________________________ __________________ ____
|
||
; _____ | |
|
||
; ViaRD | |
|
||
; ___________ ________________________
|
||
; ____ | |
|
||
; TREQ ___________|______________________|
|
||
;
|
||
;-------------------------------------------------------------------------
|
||
CudaInit
|
||
movea.l DecoderInfo.VIA1Addr(a0),a2 ; get VIA 1 base address <SM3> <SM9>
|
||
eieioSTP
|
||
ori.b #((1<<TIP)| \ ; terminate transaction <SM3>
|
||
(1<<vByteAck)),vBufB(a2) ; and set idle state <SM3> <SM9>
|
||
nop
|
||
eieioSTP
|
||
move.l #hw4msDelay,d4 ; we want to delay 4 millisecs for ADB reset to complete <SM3>
|
||
@killtime
|
||
eieioSTP
|
||
tst.b vBufB(a2) ; <SM3> <SM9>
|
||
eieioSTP
|
||
dbra d4,@killtime ; <SM3>
|
||
eieioSTP
|
||
btst.b #TReq,vBufB(a2) ; is Cuda starting a transaction??? <SM3> <SM9>
|
||
eieioSTP
|
||
bne.s @noX ; no, then continue with SyncAck <SM3>
|
||
move.l #hw4msDelay,d4 ; we want to delay 4 millisecs for ADB reset to complete <SM3>
|
||
@asyncByte
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a2) ; else, wait for that lil' interrupt to occur <SM3> <SM9>
|
||
eieioSTP
|
||
bne.s @noX ; <SM3>
|
||
dbra d4,@asyncByte ; <SM3>
|
||
@noX
|
||
eieioSTP
|
||
tst.b vSR(a2) ; clear the pending interrupt <SM9>
|
||
nop
|
||
eieioSTP
|
||
move.l #hw10msDelay,d4 ; Timeout values must exceed duration of maximum ADB auto poll. <7>
|
||
eieioSTP
|
||
bclr.b #vByteAck,vBufB(a2) ; issue a sync state (TIP = negated, ByteAck = asserted) <SM9>
|
||
nop
|
||
eieioSTP
|
||
@waitSync
|
||
eieioSTP
|
||
btst.b #TReq,vBufB(a2) ; wait for sync acknowledge <SM9>
|
||
eieioSTP
|
||
beq.s @syncAck ;
|
||
dbra.w d4,@waitSync ;
|
||
bra.l DeadCuda ; go play death chimes
|
||
@syncAck move.l #hw10msDelay,d4 ; number of retries before giving up with Cuda
|
||
@wSyncIrq
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a2) ; wait for sync acknowledge interrupt <SM9>
|
||
eieioSTP
|
||
bne.s @haveSync ;
|
||
dbra.w d4,@wSyncIrq ;
|
||
@haveSync move.l #hw10msDelay,d4 ; number of retries before giving up with Cuda
|
||
eieioSTP
|
||
bset.b #vByteAck,vBufB(a2) ; terminate the sync cycle <SM9>
|
||
nop
|
||
eieioSTP
|
||
@syncTerm
|
||
eieioSTP
|
||
btst.b #TReq,vBufB(a2) ; wait for sync termination acknowledge <SM9>
|
||
eieioSTP
|
||
bne.s @haveTerm ;
|
||
dbra.w d4,@syncTerm ;
|
||
bra.l DeadCuda ; go play death chimes
|
||
@haveTerm
|
||
eieioSTP
|
||
tst.b vSR(a2) ; clear the pending interrupt <SM9>
|
||
nop
|
||
eieioSTP
|
||
move.l #hw10msDelay,d4 ; number of retries before giving up with Cuda
|
||
@waitIdle2
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a2) ; wait for sync termination acknowledge <SM9>
|
||
eieioSTP
|
||
bne.w @haveIdle ;
|
||
dbra.w d4,@waitIdle2 ;
|
||
bra.l DeadCuda ; go play death chimes
|
||
@haveIdle ;
|
||
eieioSTP
|
||
ori.b #((1<<TIP)| \ ; terminate transaction
|
||
(1<<vByteAck)),vBufB(a2) ; and set idle state <SM9>
|
||
nop
|
||
eieioSTP
|
||
tst.b vSR(a2) ; clear the pending interrupt <SM9>
|
||
nop
|
||
eieioSTP
|
||
@exit
|
||
rts6 ; setup the return to caller of CudaInit
|
||
|
||
eject
|
||
************************************************************************************************************
|
||
* SendCudaCmd 9630: This register based routine will send up to four bytes of data to
|
||
* Cuda. The packet type, command, byte count and data are passed in
|
||
* registers. The routine will return with d0.w = $0000 if it sent the
|
||
* command successfully. A value of $FFFF signifies that the command did
|
||
* not get through. The system and Cuda hung and the system aborted the
|
||
* transaction.
|
||
*
|
||
* WARNING: This routine will not error check the transaction requested. It is the
|
||
* WARNING: responsibility of the caller to make sure that the packet type, command,
|
||
* WARNING: data and data byte count are valid for the transaction requested. Failure
|
||
* WARNING: to follow the rules will make this routine fail and CRASH the system.
|
||
*
|
||
* Input:
|
||
* a0.l Pointer to Base address table
|
||
*
|
||
* d0.l = High word PACKET Command
|
||
* Low word PACKET Type
|
||
*
|
||
* d1.l = Up to four bytes of data to send
|
||
* Long word data byte assigment = byte 4, byte 3, byte 2, byte 1
|
||
* Byte 1 sent out first
|
||
*
|
||
* d2.l = Byte count to send. (0-4 bytes)
|
||
* Byte count > 4 will send four bytes only
|
||
*
|
||
* Output: d0.w $0000 if call succeeded, Nonzero if failed
|
||
*
|
||
* d1.l high word = flags, low word packet type returned by Cuda
|
||
*
|
||
* Destroys: D2.l, D3.l, D4.l, A5.l, A4.l, A1.l
|
||
*
|
||
************************************************************************************************************
|
||
SendCudaCmd
|
||
movea.l DecoderInfo.VIA1Addr(a0),a1 ; get VIA 1 base address
|
||
move.l #((MaxTout<<16) OR MaxRetries),d4 ; number of retries before giving up with Cuda
|
||
eieioSTP
|
||
btst.b #TIP,vBufB(a1) ; check for a transaction in progress
|
||
eieioSTP
|
||
bne.s @AllOK
|
||
@Timeout
|
||
eieioSTP
|
||
ori.b #((1<<TIP)| \ ; terminate transaction
|
||
(1<<vByteAck)),vBufB(a1) ; and set idle state
|
||
nop
|
||
eieioSTP
|
||
@WaitIdle
|
||
bsr.l otherDelay
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a1) ; wait for idle state acknowledgement
|
||
eieioSTP
|
||
beq.s @WaitIdle ;
|
||
eieioSTP
|
||
tst.b vSR(a1) ; clear the idle acknowledge interrupt
|
||
nop
|
||
eieioSTP
|
||
|
||
@AllOK swap.w d4 ; timeout in low word of d4 Retry count in high word
|
||
eieioSTP
|
||
btst.b #TReq,vBufB(a1) ; check for a transaction request from Cuda
|
||
eieioSTP
|
||
beq.l IrqMissed ; MIssed Vsr Irq because of INITVIAS
|
||
bsr5 @SendPtype ; send the packet type
|
||
beq.l RealAbort ; Discard Aborting transaction
|
||
;
|
||
; If not abort transaction in progress then send the command byte
|
||
;
|
||
swap d0
|
||
bsr5 sendByte1 ; send the command byte
|
||
;
|
||
; Now send number of bytes contained in d1 based on
|
||
; byte count contained in d2.w
|
||
;
|
||
move.l d1,d0 ; get the data to send
|
||
subq #1,d2 ; adjust for DBRA
|
||
cmp.w #3,d2 ; if count out of range quit
|
||
bhi.s @EndCmd ; if count valid then adjust for dbra
|
||
@sendloop bsr5 sendByte1
|
||
lsr.l #8,d0 ; move data byte to low byte of register
|
||
@loopEntry dbra d2,@sendloop ; decrement byte count
|
||
;
|
||
; Wait for the response packet header
|
||
;
|
||
@EndCmd
|
||
|
||
eieioSTP
|
||
bclr.b #SRdir,vACR(a1) ; shift in
|
||
nop
|
||
eieioSTP
|
||
ori.b #((1<<TIP)|\ ; terminate command packet transaction
|
||
(1<<vByteAck)),vBufB(a1) ;
|
||
nop
|
||
eieioSTP
|
||
|
||
;
|
||
; Now receive the Standard Response packet Header
|
||
;
|
||
bsr5 readAttn ; get the Attention byte
|
||
eieioSTP
|
||
bclr.b #TIP,vBufB(a1) ; start the response transaction
|
||
nop
|
||
eieioSTP
|
||
|
||
bsr5 readByte ; get the packet type
|
||
and #$00FF,d0 ; keep low byte only
|
||
swap d0 ; save the packet type
|
||
|
||
bsr5 readByte ; get the flags byte
|
||
and.w #$00FF,d0 ; keep low byte only
|
||
swap d0 ; keep the flags byte as an error code
|
||
exg d0,d1 ; save the packet type and flags returned
|
||
|
||
bsr5 readByte ; get the command
|
||
eieioSTP
|
||
ori.b #((1<<TIP)|\ ; terminate command packet transaction
|
||
(1<<vByteAck)),vBufB(a1) ;
|
||
nop
|
||
eieioSTP
|
||
|
||
@WaitIdle1
|
||
bsr.l otherDelay
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a1) ; wait for idle state acknowledgement
|
||
nop
|
||
eieioSTP
|
||
beq.s @WaitIdle1 ;
|
||
eieioSTP
|
||
tst.b vSR(a1) ; clear the idle acknowledge interrupt
|
||
nop
|
||
eieioSTP
|
||
;
|
||
; Check for an error packet returned by Cuda
|
||
;
|
||
move.l d1,d0 ; save the packet type and flags
|
||
cmp.b #errorpkt,d0 ; check for error packet
|
||
beq.s @exit ; error pkt then just exit
|
||
sub.w d0,d0 ; zero for success
|
||
@exit
|
||
|
||
rts6
|
||
|
||
;--------------------------------------------------------------------------
|
||
@SendPtype
|
||
eieioSTP
|
||
bset.b #SRdir,vACR(a1) ; shift out
|
||
nop
|
||
eieioSTP
|
||
btst.b #TReq,vBufB(a1) ; check for abort
|
||
eieioSTP
|
||
beq.w AbortReq ; go away if abort requested
|
||
eieioSTP
|
||
move.b d0,vSR(a1) ; load byte into shift reg
|
||
nop
|
||
eieioSTP
|
||
bclr.b #TIP,vBufB(a1) ; TIP indicates shift reg is full on 1st byte
|
||
nop
|
||
eieioSTP
|
||
;
|
||
; Check Vsr Irq until timeout. If timeout then check the retry count
|
||
; and Call Death Chimes if Retry count exausted.
|
||
;
|
||
@PollDelay bsr.l otherDelay
|
||
btst.b #ifSR,vIFR(a1) ; wait for shift to complete
|
||
eieioSTP
|
||
bne.w VsrIrq ; Go service Shift register Irq
|
||
dbra.w d4,@PollDelay ; try again if timed out
|
||
move.w #MaxTout,d4 ; Reset the Timeout
|
||
swap.w d4 ; get the Retry count
|
||
subq.w #1,d4 ; Try again if Retry count not Exausted
|
||
bne.s @Timeout
|
||
|
||
DeadCuda
|
||
eieioSTP
|
||
ori.b #((1<<TIP)| \ ; terminate transaction
|
||
(1<<vByteAck)),vBufB(a1) ; and set idle state
|
||
nop
|
||
eieioSTP
|
||
move.l #ErrCudaInit,d7 ; Cuda failed, zero high byte flags <SM7>
|
||
move.l #0001,d6 ; d6.l must be nonzero
|
||
bra.s *
|
||
|
||
VsrIrq
|
||
move.l d4,-(sp)
|
||
move $d00,d4
|
||
divu #10,d4
|
||
dbra.w d4,*
|
||
move.l (sp)+,d4
|
||
|
||
eieioSTP
|
||
tst.b vSR(a1) ; clear the interrupt
|
||
nop
|
||
eieioSTP
|
||
btst.b #TReq,vBufB(a1) ; exit with abort status
|
||
nop
|
||
eieioSTP
|
||
AbortReq rts5
|
||
|
||
;--------------------------------------------------------------------------
|
||
; DumpAbort 9774 This routine will read all the data for an abort transaction and
|
||
; discard it. When done it will jump back to SendNopCmd entry point
|
||
; to retry our command. This command will eventually complete...
|
||
|
||
Export RealAbort
|
||
RealAbort
|
||
eieioSTP
|
||
bclr.b #SRdir,vACR(a1) ; shift in <rbm>
|
||
nop
|
||
eieioSTP
|
||
ori.b #((1<<TIP)| \ ; terminate transaction
|
||
(1<<vByteAck)),vBufB(a1) ; and set idle state
|
||
nop
|
||
eieioSTP
|
||
WAbortAck bsr.l otherDelay
|
||
btst.b #ifSR,vIFR(a1) ; wait for acknowledgement of abort cycle
|
||
eieioSTP
|
||
beq.s WAbortAck ;
|
||
tst.b vSR(a1) ; clear the pending interrupt
|
||
nop
|
||
eieioSTP
|
||
bra.s StartRPkt ; and go start the response transaction
|
||
;
|
||
; It may be possible to miss a VIA interrupt when the system is restarted because
|
||
; a transaction may have been in process when the restart occurred. During restart,
|
||
; the VIA is initialized and will result in the loss of any interrupt status. Cuda
|
||
; will complete transmission of the attention byte within 100µS of asserting TReq
|
||
; (65µS nominal). By delaying 100µS we can assume that the attention byte interrupt
|
||
; has occurred.
|
||
;
|
||
Export IrqMissed
|
||
IrqMissed
|
||
bsr5 Delay100us ; Let Cuda see SysSes. ³ 125µsec
|
||
eieioSTP
|
||
bclr.b #SRdir,vACR(a1) ; shift in
|
||
nop
|
||
eieioSTP
|
||
StartRPkt
|
||
eieioSTP
|
||
tst.b vSR(a1) ; discard the byte
|
||
nop
|
||
eieioSTP
|
||
bclr.b #TIP,vBufB(a1) ; start the response transaction
|
||
nop
|
||
eieioSTP
|
||
|
||
DumpAbort
|
||
bsr.l otherDelay
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a1) ; wait for shift to complete
|
||
eieioSTP
|
||
beq.s DumpAbort
|
||
eieioSTP
|
||
tst.b vSR(a1) ; discard the byte
|
||
nop
|
||
eieioSTP
|
||
|