mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-22 04:31:30 +00:00
2280 lines
87 KiB
Plaintext
2280 lines
87 KiB
Plaintext
;
|
||
; File: EGRET Manager.a
|
||
;
|
||
; Contains: Contains low level code to support sending and receiving
|
||
; packets (ADB, Pseudo Commands, Ticks, etc) to/from the Egret
|
||
; 6805uC.
|
||
;
|
||
; Written by: Gary Rensberger
|
||
;
|
||
; Copyright: © 1990-1993 by Apple Computer, Inc. All rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM19> 11/9/93 KW added some eieioSTP macros. Only expands for CygnusX1 ROM.
|
||
; <SM18> 9/29/93 SAM From mc900ftjesus.
|
||
; <MC3> 9/25/93 SAM Whoot! What a mess. Removed usless/redundant entry points and
|
||
; imports/exports by the thousands. Cleaned up tons of stuff.
|
||
; Changed the labels of a few routines to reflect the fact that
|
||
; they apply to both egret and cuda. Export ChkFirmware for
|
||
; vectorization. Backedout change <SM17>.
|
||
; <SM17> 9/23/93 PN Add condition for Egret
|
||
; <SM16> 7/12/93 kc Re-roll in ShiftRegIRQPatch to fix Quadra 900-950 ReadTime bug.
|
||
; <SM15> 12/1/92 RB Turned off the debug feature in Egret.
|
||
; <SM14> 11/20/92 GS Removed the CudaPDMPatch from the initialization of the DFAC and
|
||
; PDMs for Caboose or Cuda. This initialization for Cyclone is
|
||
; now done in the Gibbly.
|
||
; <SM13> 11/3/92 SWC Changed ShutdownEqu.a->Shutdown.a.
|
||
; <SM12> 10/02/92 AEK Conditionalize call to InitReliabitity to keep it from being
|
||
; called twice if not on an overpatched ROM
|
||
;
|
||
; <SM11> 9/18/92 GS Debug Enter - removed PDMSuspend command. DebugExit - add
|
||
; MacsbugContinue command, add Window update. EgretDFACandPDM
|
||
; routine - removed the Keybd NMI enable for the Cuda FW. In the
|
||
; Cuda FW, the command to enable/disable Keybd NMI no longer is a
|
||
; valid command. Keybd NMI is always enabled with the Cuda FW.
|
||
; <SM10> 6/26/92 GS (RBM) Removed the Enable KeyboardNMI call made in the
|
||
; EgretDFACandPDM
|
||
; routine. With the new version of Cuda FW (Cuda 0.22), the NMI
|
||
; is always ON.
|
||
; No longer has entry in the pseudo cmd table for SetDFACmode.
|
||
; Instead, a new
|
||
; command exists, called RdWrIIC to perform bidirectional IIC
|
||
; transactions.
|
||
; This requires special setup of the Cuda globals by the routine
|
||
; 'SetTransferParams' (see CudaMgr.a).
|
||
;
|
||
; <SM9> 5/24/92 RB Removed the routine QuadraEgretChanges since EgretDFACandPDM is
|
||
; a better version from the Pandora ROM. This routine gets called
|
||
; from StartInit.a
|
||
; <SM8> 5/24/92 RB Removing "patches" as they get rolled into the other
|
||
; sources...PowerSwitchIntPatch is out.
|
||
; <SM7> 5/23/92 RB Making Cyclone changes...Revised some patches rolled in from
|
||
; Terror. Pandora comments follow: with some duplications... Note
|
||
; that a lot of this code should be reworked with the ADBMgr, the
|
||
; first step is to get it all in... **** From EgretPatches.a: <P2>
|
||
; 4/24/92 GS Added a Egret Dispatch call to suspend/continue PDM
|
||
; when entering exiting Macsbug. This is to prevent problems of
|
||
; determining whether or not to ignore PDM messages. **** From
|
||
; EgretMgr.a: <P4> 2/10/92 GS Exported the PseudoTable for use by
|
||
; the CudaMgr.a code. Cleaned up some comments. <P3> 02/07/92 jmp
|
||
; Added some padding so that Pandora matches Horror. <P2> 1/16/92
|
||
; GS Added code to determine the Egret Firmware Type (Egret8,
|
||
; Caboose, Cuda), then set up the appropiate vectors for IRQ,
|
||
; Ticks, Dispatcher...
|
||
; ———————————————————————————————————————————————————————————————————————————————————————
|
||
; Pre-Pandora ROM comments begin here.
|
||
; ———————————————————————————————————————————————————————————————————————————————————————
|
||
; <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.
|
||
; <P9> 4/24/92 GS Removed DSorDebuggerPatch that was called from StartErr.a New
|
||
; code and PDM Selectors used by PDM removed the need. Updated
|
||
; the DebugUtil code in EgretPatches.a to handle these cases.
|
||
; **** From EgretPatchesToo.a:
|
||
; <P8> 4/24/92 KW (SWC,H5) Moved ADB and DebugUtil routines to ADBPrimitives.a.
|
||
; <P10> 4/10/92 gjs Make Timer Mgr Task fire off a Cuda Tickle pkt every 3 sec
|
||
; instead of 7 secs. Still having problem with 2nd User Alert
|
||
; with mulitple hits to Keybd Reset key. Also bump up the Timer
|
||
; Timeout passed back to Cuda.
|
||
; <P9> 4/08/92 gjs Upon installing a TimeMgr task to tickle Cuda during the User
|
||
; alert, send a tickle to cover the first 7-10 seconds of the
|
||
; display of the alert.
|
||
; <P8> 3/30/92 GS The KeyBdSwHandler has been changed to set up a User Alert
|
||
; if the KeybdPower switch has been depressed, or if the
|
||
; chassis swithc or Secure Key switch has been used for a power down
|
||
; a deferred Task will be executed, with out a User Alert.
|
||
; <P7> 3/17/92 GS The PowerSwitch Int Handler has been changed to user the new
|
||
; ShutDown mgr code in the system. This makes all _ShutDown trap
|
||
; calls with the selector set to 1 a soft power off.
|
||
; <P6> 3/3/92 GS Update some Cuda Code to save some regs in Tickle timer code,
|
||
; and begin to setup for the new power down msg to indicate kybd
|
||
; or chassis sw power down.
|
||
; <P5> 02/11/92 jmp The EgretDFACandPDAM routine (which used to be the
|
||
; EclipseEgretPatches routine) got bigger, so I moved it into the
|
||
; pad space, with a branch from the original location.
|
||
; <P4> 2/11/92 GS Update the Cuda Patches used to support SoftPower On/Off. Added
|
||
; comments and revision tags. Updated a patch label from
|
||
; EclipseEgretPatches to EgretDFACandPDM to better describe the
|
||
; function of the patch. Also added functionality to the patch to
|
||
; handle Caboose and Cuda firmware initializations.
|
||
; <P3> 02/07/92 jmp (jmp,H3/BG,Z19) Fixed ReGenSoundInt to wait in between disabling
|
||
; and re-enabling sound interrupts. Also changed ReGenSoundInt to
|
||
; work like Kip originally intended (i.e. regenerate interrupts
|
||
; only on the channel(s) that need it).
|
||
; <P2> 1/16/92 GS Rolled in the newPatches that are associated with the Cuda
|
||
; firmware for SoftPower On/Off.
|
||
; ———————————————————————————————————————————————————————————————————————————————————————
|
||
; Pre-Pandora ROM comments begin here. (EgretPatchesToo)
|
||
; ———————————————————————————————————————————————————————————————————————————————————————
|
||
; <H2> 12/21/91 jmp (BG,Z18) Added code to re-generate sound interrupts when
|
||
; checking the keyswitch values since reading port B causes
|
||
; interrupts to get cleared (stupid design of original VIAs).
|
||
;
|
||
; <SM6> 5/17/92 kc Roll in Horror sources. (prepend via equates with v)
|
||
; <SM5> 5/13/92 SES Fixed bug in ShiftRegIrq patch roll in. Additional sr restore
|
||
; instructions were added only where necessary instead of trying
|
||
; to restore "globally" right before exiting.
|
||
; <SM4> 5/5/92 SES Rolled in patches from PatchIIciROM.a, including ShiftRegIrq
|
||
; patch for saving/restoring sr, and addition of SCC polling in
|
||
; EgretDispatch. Also fixed minor bug in tickHandler where
|
||
; with/endwith directives were left out.
|
||
; <SM3> 5/4/92 FM fix typo
|
||
; <SM2> 5/4/92 FM Roll in changes from PatchIICiRom.a file that were "lost" in the
|
||
; review process… Changing the TickHandler to update the Time
|
||
; lo-mem global so that the RdDateTime can simply return whats in
|
||
; the global.
|
||
; <21> 1/20/92 KC Move RequestDonePatch into ADBMgr.a. Changed
|
||
; CheckForCabooseKeyswitch into TestFor KeyswCabooseBit macro
|
||
; call.
|
||
; <20> 1/13/92 kc Added Terror changes, origional comments below.
|
||
; {?} Added "Enable PDMMessage" and "SendDefault DFAC" to PseudoCntTable.
|
||
; {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.
|
||
; <19> 12/29/91 RB Added Terror changes and rolled in patches to support Quadras.
|
||
; <18> 8/30/91 JSM Cleanup header, don’t include SysErr.a since it’s in
|
||
; StandardEqu.d.
|
||
; <17> 6/12/91 LN removed #include 'HardwareEqu.a'
|
||
; <16> 4/24/91 dba fix warning
|
||
; <15> 10/22/90 JJ Rex V8: Change VISAChipBit to V8ChipBit.
|
||
; <14> 5/15/90 GA Removing calls to SCCPollDelay. Routine not needed.
|
||
; <13> 5/8/90 GA Disabled all interrupts during interrupt handler to prevent
|
||
; AppleTalk from interrupting Egret Manager and the issuing a
|
||
; ReadXPram call which calls Egret Manager Synchronously. Changed
|
||
; the Delay100 routine to SCCPollDelay. It polls and buffers any
|
||
; serial data from the SCC and calls the Serial Driver PollProc
|
||
; routine if one is present. Modified SendEgretCmd to have a retry
|
||
; count to communicate with Egret. If the Retry count expires,
|
||
; EgretMgr calls Error1Handler. Modified SendPtype to read the
|
||
; interrupt flags register in the via 32767 times (≈41.9 millsecs
|
||
; max) and then try send the packet type again based on the retry
|
||
; count.
|
||
; <12> 4/25/90 GA Fixed a bug with SendDFAC to allow 1 to 4 bytes to be sent to
|
||
; Egret. Fixed a bug with the error reporting mechanism to return
|
||
; all 4 bytes of the error packet returned by Egret.
|
||
; <11> 4/10/90 GA Fixed a bug in the error checking code. Made a change to make
|
||
; KeyLite program work (returns parameter block byte count
|
||
; unchanged).
|
||
; <10> 4/2/90 GA Removing the Routine Read LastByte from the SendEgretCmd code.
|
||
; Also, fixing lines of source which have had their C/R changed to
|
||
; a Null ($00) character. We suspect that Romlister may trash
|
||
; source files which are open during the build.
|
||
; <9> 3/30/90 GA Added Error reporting for bad parameter blocks from the system
|
||
; to Egret.
|
||
; <8> 3/22/90 GA Changed the Via_Full Ack process on the last byte of
|
||
; transactions to clarify the Logic Analyzer displays.
|
||
; <7> 3/15/90 GA Ray and I added conditionalized code to send Stop Autopoll and
|
||
; send mode 0 one second interrupt command s in place of the
|
||
; SendNOPCmd to support the B3 release of Egret. This code will be
|
||
; inactivated when the final Egret parts come in.
|
||
; <6> 3/13/90 GA Added a routine called SENDNOPCMD. This routine is register
|
||
; driven and issues a command to Egret to Stop AutoPoll and one
|
||
; second interrupts in Egret
|
||
; <5> 3/9/90 GMR Optimized code in a few places. Moved assertion of SysSes bit to
|
||
; after test of XcvrSes, to fix bug on 2 byte tick packets.
|
||
; <4> 2/28/90 GMR Rewrote file.
|
||
; <3> 2/14/90 GA Added support code for Restart & shutdown in Egret. Issues stop
|
||
; autopoll & stop 1 sec interrupts prior to restarting the system.
|
||
; <2> 2/9/90 GA 1. Added two calls to DelayLoop to give Egret time to see
|
||
; transitions of SysSession signal.
|
||
;
|
||
; 2. SendWithCheck & SynChkSend now wait for the shift register
|
||
; interrupt bit to be asserted before exiting when a transaction
|
||
; is aborted.
|
||
;
|
||
; 3. Moved code which sends bitmap and starts autopoll to Egret into
|
||
; EgretMgr.a. ADBMgr now issues a JSR StartEgretAutopoll to do
|
||
; the same function. This makes the Erickson overpatch easier.
|
||
;
|
||
; <1> 2/3/90 GA first checked in
|
||
;
|
||
************************************************************************
|
||
machine mc68020
|
||
|
||
BLANKS ON
|
||
STRING ASIS
|
||
|
||
PRINT OFF
|
||
LOAD 'StandardEqu.d'
|
||
INCLUDE 'EgretEqu.a'
|
||
INCLUDE 'HardwarePrivateEqu.a'
|
||
INCLUDE 'UniversalEqu.a'
|
||
INCLUDE 'IOPEqu.a'
|
||
INCLUDE 'AppleDeskBusPriv.a'
|
||
INCLUDE 'ShutDown.a'
|
||
INCLUDE 'FSEqu.a'
|
||
INCLUDE 'PowerPrivEqu.a'
|
||
PRINT ON
|
||
|
||
include 'EgretEqu.a'
|
||
eject
|
||
|
||
EgretDebug EQU 0
|
||
|
||
EgretMgr PROC EXPORT
|
||
|
||
EXPORT InitEgretOrCuda, EgretDispatch, CheckPacket
|
||
EXPORT PseudoCntTable, ADBCntTable, SetResponseParams, ChkFirmware
|
||
|
||
IMPORT GetHardwareInfo, Error1Handler
|
||
IMPORT CudaDispatch,CudaShiftRegIRQ,CudaTickHandler
|
||
IMPORT CudaInit, SendCudaCmd
|
||
|
||
rayFix EQU 1 ; needed to fix Egret bug on old parts
|
||
ErrEgretInit equ $0030 ; TEMPORARY definition of error equate defined in STEQU.a
|
||
|
||
|
||
WITH EgretGlobals,EgretPB,RespHeader ; <60> rb
|
||
;===============================================================================================
|
||
; Routine: InitEgret
|
||
;
|
||
; Function: Allocates globals, sets vACR to shift in mode, sets up globals for an auto-response
|
||
; packet (ADB/Ticks).
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Destroys: a0-a2, d0-d2
|
||
;________________________________________________________________________________________________
|
||
InitEgretOrCuda
|
||
moveq.l #EgretGlobSize,D0 ; get size of globals
|
||
_NewPtr ,SYS,CLEAR ; allocate space on heap and clear
|
||
|
||
move.l a0,EgretBase ; save ptr to it
|
||
movea.l a0,a2 ;
|
||
|
||
move.w sr,-(sp) ; save irq enable status
|
||
ori.w #HiIntMask,sr ; mask out interrupts
|
||
|
||
lea workPb(a2),a0 ; pointer to work parameter block <SM7> rb
|
||
move.l a0,adbPb(a2) ; store in adb parameter block <SM7> rb
|
||
|
||
bsr SetResponseParams ; setup globals to handle auto response packets again
|
||
|
||
bsr.l ChkFirmware ; Set up dispatch,IRQ, and ticks (Sets up _EgretDispatch trap)
|
||
move.l a0,Lvl1DT+8 ; the level 1 dispatch table
|
||
move.l a1,tickComp(a2) ; set up default tick packet handler
|
||
|
||
movea.l VIA,a1 ; point to the VIA
|
||
eieioSTP
|
||
bclr.b #SRdir,vACR(a1) ; shift reg direction = input
|
||
eieioSTP
|
||
move.b #(1<<ifIRQ)|\
|
||
(1<<ifSR),vIER(a1) ; enable shift register interrupts
|
||
eieioSTP
|
||
move.w (sp)+,sr ; restore interrupts
|
||
rts
|
||
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: EgretDispatch
|
||
;
|
||
; Function: This is the Egret manager trap routine. It waits for Egret to be idle, sends
|
||
; the first byte of the command packet. If Egret 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
|
||
;
|
||
; Outputs: d0 - result (0 for now)
|
||
;
|
||
; Destroys: a0-a2, d0-d1
|
||
;________________________________________________________________________________________________
|
||
EgretDispatch
|
||
bsr CheckPacket ; Validate the Packet type & command byte
|
||
bne @done ; Exit if Error packet
|
||
movea.l EgretBase,a2 ; a2 gets ptr to globals
|
||
movea.l VIA,a1 ; a1 points to VIA base
|
||
|
||
|
||
|
||
@checkSpecial
|
||
cmpi.b #specialPkt,pbCmdType(a0) ; is this a special command? <SM7> rb
|
||
bne.s @ckPDMInit ; check for Eclipse PowerDown Message Initialization <SM7> rb
|
||
|
||
move.l a0,ADBpb(a2) ; yes, is to set the ADB param block (for autopoll data). <SM7> rb
|
||
bra @done ; <SM7> rb
|
||
|
||
@ckPDMInit ; <SM7> rb
|
||
;
|
||
; Check for Eclipse PowerDown Message Vector
|
||
; Initialization.
|
||
;
|
||
cmpi.b #PDMVectPkt,pbCmdType(a0) ; check for PowerDown message vector Init <60> rb <SM7> rb
|
||
bne.s @EgretRestart ; Must be Egret Command <60> rb <SM7> rb
|
||
|
||
move.l pbParam(a0),PDMComp(a2) ; handler for Eclipse PowerDown Message Packet <60> rb <SM7> rb
|
||
bra @done ; and exit
|
||
|
||
@EgretRestart
|
||
|
||
|
||
move.w sr,-(sp) ; save SR
|
||
ori.w #hiIntMask,sr ; mask interrupts
|
||
eieioSTP
|
||
btst.b #xcvrSes,vBufB(a1) ; does Egret want to abort?
|
||
eieioSTP
|
||
beq.s @abort ; yes, wait for it to go away
|
||
bset.b #busy,flags(a2) ; not an abort, mark that we're busy.
|
||
eieioSTP
|
||
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
|
||
bsr pollByte ; poll shift reg, calling handler if interrupts masked
|
||
|
||
bra.s @EgretRestart ; and keep waiting for busy to go away...
|
||
|
||
@sendPackType ; interrupts masked here
|
||
eieioSTP
|
||
bset.b #sysSes,vBufB(a1) ; assert System Session (we're starting command packet)
|
||
eieioSTP
|
||
bset.b #SRdir,vACR(a1) ; switch to output
|
||
eieioSTP
|
||
move.b pbCmdType(a0),vSR(a1) ; send command packet to shift reg
|
||
eieioSTP
|
||
bset.b #viaFull,vBufB(a1) ; tell Egret we sent it
|
||
eieioSTP
|
||
|
||
;<SM4><SES> Rolled in from PatchIIciROM.a
|
||
;----------------------------------------------------------------------------------------------------
|
||
; This patch fixes possible loss of data to the SCC by calling
|
||
; the Poll Proc when SCC data is available.
|
||
;
|
||
; NOTE: This is a slightly modified version of the one from PatchIIciROM.a
|
||
;----------------------------------------------------------------------------------------------------
|
||
;_________________________
|
||
; 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/d1/a0-a4/a6,-(sp) ; save some registers
|
||
|
||
move.l sp,PollStack ; Pointer to buffer for polled bytes
|
||
|
||
eieioSTP
|
||
btst.b #0,SccIopFlag ; Check if we are in IOP mode (On Eclipse...)
|
||
eieioSTP
|
||
beq.s @NoPollWait ; If IOP then we don't need to poll
|
||
|
||
tst.l PollProc ; Check for a Poll Proc available
|
||
beq.s @NoPollWait ; If no Poll Proc then we don't need to poll
|
||
|
||
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
|
||
eieioSTP
|
||
btst.b #RxCa,(a3) ; Test for SCC data available
|
||
eieioSTP
|
||
beq.s @2
|
||
move.b (a6),-(sp) ; Push the data on the stack
|
||
@2
|
||
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
|
||
|
||
|
||
@NoPollWait
|
||
eieioSTP
|
||
btst.b #vShift,vIFR(a1) ; now wait for shift reg IRQ
|
||
eieioSTP
|
||
|
||
beq.s @NoPollWait
|
||
|
||
@NoSCCData movem.l (sp)+,d0/d1/a0-a4/a6 ; restore work registers
|
||
|
||
@VsrIrq
|
||
eieioSTP
|
||
btst.b #xcvrSes,vBufB(a1) ; did Egret abort?
|
||
eieioSTP
|
||
bne.s @accepted ; no, then it will accept our packet
|
||
bclr.b #SRdir,vACR(a1) ; yes, switch back to input
|
||
eieioSTP
|
||
bclr.b #sysSes,vBufB(a1) ; ack the abort
|
||
eieioSTP
|
||
bsr CallShiftRegIRQ ; handle it
|
||
eieioSTP
|
||
bra.s @abort ; and wait
|
||
|
||
;<SM4><SES> end of EgretDispatch SCC poll fix
|
||
|
||
@accepted ; we sent the packetType, now set up for the IRQ handler
|
||
jsr SetTransferParams ; setup globals for this packet
|
||
bsr CallShiftRegIRQ ; transfer second byte (command) to start things
|
||
move.w (sp)+,sr ; now enable interrupts
|
||
eieioSTP
|
||
|
||
tst.l pbCompletion(a0) ; do we have a completion routine
|
||
eieioSTP
|
||
bne.s @done ; yes, then return asynchronously
|
||
|
||
@waitComplete
|
||
btst.b #busy,flags(a2) ; otherwise, are we still busy?
|
||
eieioSTP
|
||
beq.s @done ; no, then we're done...
|
||
|
||
bsr.s pollByte ; yes, poll out a byte if necessary
|
||
|
||
; bclr.b #busy,flags(a2) ; otherwise, are we still busy?
|
||
|
||
bra.s @waitComplete ; and wait here (synchronously)
|
||
|
||
@done moveq #0,d0 ; no errors for now
|
||
rts
|
||
|
||
;________________________________________________________________________________________________
|
||
;
|
||
; Validate the Packet type and Command if Pseudo Pkt.
|
||
;
|
||
; If an error is encountered with the packet a error packet will be
|
||
; built in the pbParam area of the parameter block as if Egret had
|
||
; returned the packet. Also, the pbResult field will contain a System
|
||
; error code for bad parameter block format.
|
||
;
|
||
; Entry: A0 = Parameter block pointer
|
||
;
|
||
; Exit: sr.Z = 0 if valid packet/pseudocmd nonzero otherwise
|
||
;
|
||
_________________________________________________________________________________________________
|
||
|
||
CheckPacket
|
||
cmp.b #SpecialPkt,pbCmdType(a0) ; could be an ADB initialization packet
|
||
beq.s @OkExit
|
||
|
||
cmp.b #PDMVectPkt,pbCmdType(a0) ; could be PowerDown message Vector Init Packet <60> rb
|
||
beq.s @OKExit ; if equal, CONTINUE <60> rb
|
||
|
||
cmp.b #ErrorPkt,pbCmdType(a0) ; ADB ($00) and Pseudo ($01) only
|
||
bhi.s @BadPkt ; Invalid packet
|
||
|
||
cmp.b #PseudoPkt,pbCmdType(a0) ; Check for pseudo commands
|
||
bne.s @OkExit ; On Pseudo Packets check the command
|
||
|
||
cmp.b #MaxPseudoCmd,pbCmd(a0) ; Validate the Pseudo command number {5}
|
||
bls.s @OkExit
|
||
|
||
@BadPseudo move.w #InvPseudo,pbParam(a0) ; report a pseudo command error
|
||
move.w pbCmdType(a0),pbParam+2(a0) ; we are faking an error packet
|
||
bra.s @ErrorExit
|
||
|
||
@BadPkt move.w #InvPkt,pbParam(a0) ; report invalid packet error
|
||
move.w pbCmdType(a0),pbParam+2(a0) ; we are faking an error packet
|
||
|
||
@ErrorExit move.w #paramErr,pbResult(a0) ; parameter error in result field
|
||
bra.s @Exit
|
||
|
||
@OkExit move.w #0,pbResult(a0) ; So far packet OK
|
||
@Exit rts
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: PollByte
|
||
;
|
||
; 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
|
||
;________________________________________________________________________________________________
|
||
PollByte
|
||
|
||
move.w sr,d0 ; get 68xxx interrupt mask
|
||
andi.w #hiIntMask,d0 ; are we at interrupt level?
|
||
beq.s @exit ; no, just exit
|
||
eieioSTP
|
||
btst.b #vShift,vIFR(a1) ; yes, poll the shift reg
|
||
eieioSTP
|
||
beq.s @exit ; no shift reg interrupt, return
|
||
bsr.s CallShiftRegIRQ ; yes, handle it
|
||
@exit rts
|
||
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: SendByte
|
||
;
|
||
; Function: This routine clears viaFull bit, delays 125us, sends a byte to the shift reg,
|
||
; then asserts viaFull bit.
|
||
;
|
||
; Inputs: d0 - byte to send
|
||
; a1 - VIA base ptr
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Destroys: d1
|
||
;________________________________________________________________________________________________
|
||
SendByte
|
||
eieioSTP
|
||
bclr.b #viaFull,vBufB(a1) ; negate via full
|
||
eieioSTP
|
||
bsr.s Delay100 ; give Egret time to see it
|
||
eieioSTP
|
||
move.b d0,vSR(a1) ; send the byte to the shift reg
|
||
eieioSTP
|
||
bset.b #viaFull,vBufB(a1) ; let Egret know it's there
|
||
eieioSTP
|
||
rts
|
||
|
||
;________________________________________________________________________________________________
|
||
CallShiftRegIRQ
|
||
movem.l a0-a3/d0-d3,-(sp) ; save regs like interrupt handler does
|
||
movea.l Lvl1DT+8,a0 ; get the shift reg IRQ handler
|
||
jsr (a0) ; call it
|
||
movem.l (sp)+,a0-a3/d0-d3 ; restore regs
|
||
rts
|
||
|
||
;________________________________________________________________________________________________
|
||
viaFullAck
|
||
eieioSTP
|
||
bset.b #viaFull,vBufB(a1) ; acknowlege the byte
|
||
eieioSTP
|
||
bsr.s Delay100 ; give Egret time to see it
|
||
eieioSTP
|
||
rts ; gets cleared on exit from IRQ handler
|
||
|
||
;________________________________________________________________________________________________
|
||
Delay100
|
||
move.l d1,-(sp) ; save d1
|
||
move.w timeViaDB,d1 ; 1 ms loop count
|
||
lsr.w #3,d1 ; / 8 = 125 us
|
||
; cmpi.b #boxQuadra900,boxFlag ; is this a Quadra900 ? <60> rb
|
||
; bne.s @loop ; no ? then skip <60> rb
|
||
add.w #EclipseDelay,d1 ; <60> rb, we need an extra 25 usecs on Eclipse <GAA Eclipse>
|
||
@loop
|
||
eieioSTP
|
||
tst.b (a1) ; access the VIA
|
||
eieioSTP
|
||
dbra d1,@loop
|
||
move.l (sp)+,d1 ; restore d1
|
||
eieioSTP
|
||
rts
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: ShiftRegIRQ
|
||
;
|
||
; 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).
|
||
;
|
||
; Inputs: a1 - VIA base ptr
|
||
;
|
||
; Outputs: a2 - globals pointer
|
||
;
|
||
; Destroys: a0-a2,d0,d1
|
||
;________________________________________________________________________________________________
|
||
EXPORT ShiftRegIRQ
|
||
|
||
ShiftRegIRQ
|
||
move.w sr,d3
|
||
ori.w #hiIntMask,sr ; mask interrupts <13>
|
||
movea.l EgretBase,a2 ; get ptr to globals <13>
|
||
bset.b #busy,flags(a2) ; make sure we're marked as busy
|
||
eieioSTP
|
||
|
||
btst.b #SRdir,vACR(a1) ; see if VIA direction is output
|
||
eieioSTP
|
||
beq.s @input ; no, then we're receiving..
|
||
|
||
tst.b vSR(a1) ; clear the shift reg interrupt
|
||
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
|
||
move.w d3,sr ; restore interrupts <SM5><SES>
|
||
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
|
||
move.w d3,sr ; restore interrupts <SM5><SES>
|
||
bra @exit ; and exit
|
||
@CmdFinished
|
||
eieioSTP
|
||
|
||
bclr.b #SRdir,vACR(a1) ; now switch to input
|
||
@sendCmd
|
||
eieioSTP
|
||
andi.b #~((1<<viaFull) | \ ; negate VIA full bit
|
||
(1<<sysSes)),vBufB(a1) ; negate System Session
|
||
eieioSTP
|
||
bsr.s Delay100 ; give Egret time to see System Session
|
||
move.w d3,sr ; restore interrupts <SM5><SES>
|
||
bra @exit ; and exit
|
||
|
||
@input ;-----------------------------------------------------------------------------
|
||
eieioSTP
|
||
move.b vSR(a1),d0 ; read the byte from shift reg into D0
|
||
eieioSTP
|
||
tst.w rcvHdrCnt(a2) ; any bytes left in response packet header?
|
||
ble.s @ckRcvData ; if not then must be data byte
|
||
|
||
@getHdrByte
|
||
eieioSTP
|
||
btst.b #sysSes,vBufB(a1) ; is System Session asserted?
|
||
eieioSTP
|
||
bne.s @notFirst ; yes, then this is not the first byte
|
||
bsr.s Delay100 ; delay 100us
|
||
bra.s @stuff
|
||
@notFirst
|
||
bsr.s viaFullAck ; acknowlege the byte using via full
|
||
@stuff 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
|
||
ble.s @CheckError ; <12>
|
||
eieioSTP
|
||
btst.b #xcvrSes,vBufB(a1) ; is Egret done?
|
||
eieioSTP
|
||
bne.s @done ; yes, we're through...
|
||
bset.b #sysSes,vBufB(a1) ; make sure System Session is asserted <5>
|
||
eieioSTP
|
||
bra @exitRd ; not done with header yet... exit
|
||
|
||
@ckRcvData
|
||
movea.l rcvDataPtr(a2),a0 ; get ptr to receive data buffer
|
||
move.b d0,(a0)+ ; store the data byte
|
||
move.l a0,rcvDataPtr(a2) ; and update header 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?
|
||
|
||
eieioSTP
|
||
beq.s @ack ; no, normal acknowlege
|
||
bsr.s viaFullAck ; acknowlege the byte using via full <8>
|
||
eieioSTP
|
||
bclr.b #sysSes,vBufB(a1) ; yes, let Egret know we don't want more <8>
|
||
@wait
|
||
eieioSTP
|
||
btst.b #xcvrSes,vBufB(a1) ; wait for egret to acknowledge termination <8>
|
||
eieioSTP
|
||
beq.s @wait ; branch until xcvr session goes high <8>
|
||
bra.s @done ; and we're done
|
||
|
||
;
|
||
; If we have an error packet in progres then read 5 bytes instead of 4 for the header. <12>
|
||
; A flag will be set on the fourth byte of an error packet and will be cleared <12>
|
||
; after reading the fifth byte of the error packet. <12>
|
||
|
||
@CheckError lea rcvHeader(a2),a0 ; point to header buffer <12>
|
||
cmp.b #ErrorPkt,1(a0) ; check packet type for error packet <12>
|
||
bne.s @CheckDone ; not an error packet go check for data <12>
|
||
|
||
bclr.b #BadPkt,flags(a2) ; check for error packet in progress flag <12>
|
||
bne.s @CheckDone ; we read the fifth byte of the error packet <12>
|
||
@readbyte5 addq.w #1,rcvHdrCnt(a2) ; adjust the count before reading the fifth byte <12>
|
||
bset.b #BadPkt,flags(a2) ; set the flag then read the fifth byte <12>
|
||
bra @exitRd ; <12>
|
||
|
||
;
|
||
; Acknowledge the data byte
|
||
;
|
||
@ack bsr.s viaFullAck ; normal byte, acknowlege it
|
||
@checkDone
|
||
eieioSTP
|
||
btst.b #xcvrSes,vBufB(a1) ; was that Egrets last byte?
|
||
eieioSTP
|
||
bne.s @done ; yes, we're through...
|
||
tst.w rcvDataCnt(a2) ; any receive data bytes to get?
|
||
bgt @exitRd ; yes, then just exit
|
||
|
||
;---------------------------------------------------------------------------
|
||
@done
|
||
eieioSTP
|
||
bclr.b #viaFull,vBufB(a1) ; make sure via full is low
|
||
eieioSTP
|
||
bclr.b #sysSes,vBufB(a1) ; let Egret know we're done
|
||
eieioSTP
|
||
bsr delay100 ; Give Egret time to see transitions & Poll SCC <13>
|
||
|
||
movea.l curPb(a2),a0 ; a0 points to current param block
|
||
lea rcvHeader(a2),a1 ; a1 points to header buffer <11>
|
||
cmp.b #ErrorPkt,1(a1) ; check for Error response packet <11>
|
||
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) <11>
|
||
move.w #paramErr,pbResult(a0) ; and return a parameter block error <11>
|
||
|
||
@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
|
||
IF rayFix THEN
|
||
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
|
||
eieioSTP
|
||
@skip
|
||
ENDIF
|
||
|
||
btst.b #EgAutoPoll,2(a1) ; check status, is this AutoPoll data?
|
||
eieioSTP
|
||
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 <11>
|
||
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
|
||
eieioSTP
|
||
@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
|
||
bsr SetResponseParams ; setup globals to handle auto response packets again
|
||
move.w d3,sr ; restore interrupts
|
||
move.l (sp)+,a0 ; restore param block ptr
|
||
jmp (a1) ; and call it
|
||
|
||
|
||
;--------------------------------------------------------------------------------------------
|
||
; AutoPoll or Tick data, push it on stack and call completion rtn
|
||
|
||
@implicit
|
||
tst.b RespPktType(a1) ; is this an ADB response? <SM16>.start
|
||
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 #PDMPkt,RespPktType(a1) ; is this a PowerDown Message Packet?
|
||
beq.s @ckPowerDownComp ; yes, handle it
|
||
|
||
cmpi.b #pseudoPkt,RespPktType(a1) ; is this a pseudo command?
|
||
bne.s @InvalidPacket ; no, something is wrong
|
||
|
||
cmpi.b #RdTime,RespCmd(a1) ; is this a read time response?
|
||
beq.s @ckTickComp ; yes, handle it
|
||
|
||
@InvalidPacket
|
||
IF EgretDebug THEN ; We have an invalid packet
|
||
|
||
pea @InvPktStr ; call Macsbug
|
||
_DebugStr
|
||
bra.s @exitNoComp ; exit without completion
|
||
|
||
@InvPktStr dc.b $14,'INVALID EGRET Packet' ; Egret error string
|
||
align
|
||
Else
|
||
bra.s @exitNoComp ; exit without completion
|
||
Endif
|
||
|
||
@ckPowerDownComp
|
||
; call service routine if it exists. <SM16>.end
|
||
move.l PDMComp(a2),d2 ; get the completion routine address
|
||
beq.s @exitNoComp ; go away if vector is null
|
||
move.l d2,a3 ; call the Service routine
|
||
move.b RespCmd(a1),d0 ; get the powerDown Switch destination position
|
||
bsr.l SetResponseParams ; setup globals to handle auto response packets again
|
||
move.w d3,sr ; restore interrupts
|
||
jsr (a3)
|
||
bra.s @exit
|
||
|
||
|
||
@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
|
||
IF rayFix THEN
|
||
bset.b #EgAutoPoll,2(a1) ; Set AutoPoll bit to fix bug in old Egret parts
|
||
ENDIF
|
||
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)
|
||
bsr SetResponseParams ; 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
|
||
jsr (a3) ; call it (a0 points to param block for ADB)
|
||
|
||
adda.w #12,sp ; pop buffer
|
||
bra.s @exit ; and exit
|
||
|
||
@exitNoComp ; no completion routine specified,
|
||
bsr SetResponseParams ; setup globals to handle auto response packets again
|
||
move.w d3,sr ; restore interrupts
|
||
bra.s @exit ; and exit
|
||
|
||
@exitRd
|
||
eieioSTP
|
||
bclr.b #viaFull,vBufB(a1) ; make sure via full is low
|
||
eieioSTP
|
||
move.w d3,sr ; restore interrupts <SM5><SES>
|
||
@exit rts
|
||
|
||
|
||
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: SetTransferParams
|
||
;
|
||
; 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
|
||
; a2 - Ptr to globals
|
||
;
|
||
; Outputs: none
|
||
; Destroys: d0,d1
|
||
;________________________________________________________________________________________________
|
||
SetTransferParams
|
||
move.l a1,-(sp) ; save a1
|
||
lea pbCmd(a0),a1
|
||
move.l a1,sendHdrPtr(a2) ; point to 1st byte of header to send
|
||
eieioSTP
|
||
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
|
||
lea ADBCntTable,a1 ; get ptr to our ADB command table
|
||
bra.s @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>
|
||
eieioSTP
|
||
move.w #0,sendDataCnt(a2) ; do not send the bytes as data also <12>
|
||
eieioSTP
|
||
clr.w sendDataCnt(a2) ; no extended data bytes <12>
|
||
eieioSTP
|
||
clr.l sendDataPtr(a2) ; no extended data ptr <12>
|
||
eieioSTP
|
||
bra.s @rcvParams
|
||
|
||
@notDFAC lea 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
|
||
eieioSTP
|
||
clr.w sendDataCnt(a2) ; no extended data bytes
|
||
eieioSTP
|
||
clr.l sendDataPtr(a2) ; no extended data ptr
|
||
eieioSTP
|
||
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
|
||
eieioSTP
|
||
move.w pbByteCnt(a0),sendDataCnt(a2) ; set up data byte count
|
||
eieioSTP
|
||
move.l pbBufPtr(a0),sendDataPtr(a2) ; set up send data ptr
|
||
eieioSTP
|
||
|
||
@rcvParams clr.w rcvHdrIndex(a2) ; reset index into header buffer
|
||
eieioSTP
|
||
move.w #4,rcvHdrCnt(a2) ; 4 byte header default
|
||
eieioSTP
|
||
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
|
||
eieioSTP
|
||
move.l a1,rcvDataPtr(a2)
|
||
eieioSTP
|
||
move.w d1,rcvDataCnt(a2) ; get receive count from table
|
||
eieioSTP
|
||
bra.s @exit ; and exit
|
||
|
||
@rcvADB add.w d1,rcvHdrCnt(a2) ; total header bytes = 4 + ADB data
|
||
eieioSTP
|
||
clr.w rcvDataCnt(a2) ; not used
|
||
eieioSTP
|
||
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
|
||
eieioSTP
|
||
move.l pbBufPtr(a0),rcvDataPtr(a2) ; set up received data buffer ptr
|
||
eieioSTP
|
||
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
|
||
eieioSTP
|
||
movea.l (sp)+,a1 ; restore a1
|
||
rts
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: SetResponseParams
|
||
;
|
||
; Function: This routine sets up transmit/receive ptrs (globals) for an auto response packet
|
||
; (e.g. ticks, ADB autopoll data), for use by the Shift Reg interrupt handler.
|
||
;
|
||
; Inputs: a2 - Ptr to globals
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Destroys: none
|
||
;________________________________________________________________________________________________
|
||
SetResponseParams
|
||
clr.l sendHdrPtr(a2) ; no command packet params
|
||
clr.w sendHdrCnt(a2) ;
|
||
clr.w sendDataCnt(a2) ;
|
||
clr.l sendDataPtr(a2) ;
|
||
|
||
move.w #12,rcvHdrCnt(a2) ; receive up to 12 response header bytes
|
||
clr.w rcvHdrIndex(a2) ; reset response header index
|
||
clr.w rcvDataCnt(a2) ; no extended data bytes
|
||
clr.l rcvDataPtr(a2) ; no receive data buffer
|
||
move.l adbPb(a2),curPb(a2) ; point to adb's autopoll param block
|
||
|
||
andi.b #~((1<<busy)|\ ; we're not busy now
|
||
(1<<openData)),flags(a2) ; we're not expecting an open ended data packet
|
||
|
||
rts
|
||
|
||
|
||
; <SM4><SES> put back function banner
|
||
;________________________________________________________________________________________________
|
||
; Routine: tickHandler
|
||
;
|
||
; Function: This is the completion routine for tick response packets.
|
||
;
|
||
; Inputs: a2 - ptr to globals
|
||
; (sp) - points to response packet
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Destroys: ???
|
||
;________________________________________________________________________________________________
|
||
; <SM22> FM This patch was rolled in from the PatchIIciRom.a file.
|
||
; <SM22> FM Its purpose is to keep the tim lo-mem up to date at
|
||
; <SM22> FM interrupt time so that the RdDateTime trap can simply
|
||
; <SM22> FM read the Time lo-mem global.
|
||
;----------------------------------------------------------------------------------------------------
|
||
; 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
|
||
;
|
||
;----------------------------------------------------------------------------------------------------
|
||
EXPORT TickHandler
|
||
TickHandler
|
||
WITH respPacket,EgretGlobals ; <SM4><SES>
|
||
|
||
subq.l #2,a1 ; <SM22> FM point to the beginning of the Response data buffer
|
||
cmpi.b #TickPkt,respPacket.respType(a1) ; <SM22> FM Check the Packet type
|
||
beq.s @CallLVL1DT ; <SM22> FM 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 respPacket.respData(a1),Time ; <SM22> FM write the new time in lowmem TIME
|
||
subq.l #1,Time ; <SM22> FM 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
|
||
jmp (a0)
|
||
|
||
ENDWITH ; <SM4><SES>
|
||
|
||
|
||
;________________________________________________________________________________________________
|
||
; These tables contain the transmit byte count and receive byte counts for each Egret command,
|
||
; one table for pseudo commands, and one table for ADB commands.
|
||
;
|
||
; tx byte cnt
|
||
; ____________
|
||
; bit 7 = 1 means pbByteCnt = number of data bytes to send after header
|
||
; bit 6-0 = # of pbParam bytes to send (in header)
|
||
;
|
||
; rx byte cnt
|
||
; ____________
|
||
; bit 7 = 1 means open ended read call (e.g. read6805, readPram)
|
||
; bit 6-0 = Pseudo Cmds: # of pbParam bytes to read into (after 4 byte header)
|
||
; bit 6-0 = ADB Cmds: # of data bytes to read into pbBufPtr
|
||
;________________________________________________________________________________________________
|
||
|
||
PseudoCntTable
|
||
dc.b $00, $00 ; 00 NoOperation send 0 bytes, receive 0 data bytes
|
||
dc.b $01, $00 ; 01 StartStopAutopoll send 1 byte, receive 0 data bytes
|
||
dc.b $02, $FF ; 02 Read6805 send 2 bytes, receive n data bytes
|
||
dc.b $00, $04 ; 03 ReadClock send 0 bytes, receive n data bytes
|
||
dc.b $00, $02 ; 04 GetRomSize send 0 bytes, receive 2 data bytes
|
||
dc.b $00, $02 ; 05 GetRomBase send 0 bytes, receive 2 data bytes
|
||
dc.b $00, $02 ; 06 GetRomHeader send 0 bytes, receive 2 data bytes
|
||
dc.b $02, $FF ; 07 ReadPRAM send 2 bytes, receive n data bytes
|
||
dc.b $82, $00 ; 08 Write6805 send 2+n bytes, receive 0 data bytes
|
||
dc.b $04, $00 ; 09 SetClock send 4 bytes, receive 0 data bytes
|
||
dc.b $00, $00 ; 0A PowerDown send 0 bytes, receive 0 data bytes
|
||
dc.b $04, $00 ; 0B SetPowerUp send 4 bytes, receive 0 data bytes
|
||
dc.b $82, $00 ; 0C WritePRAM send 2+n bytes, receive 0 data bytes
|
||
dc.b $01, $00 ; 0D SetResetFlag send 1 bytes, receive 0 data bytes
|
||
dc.b $01, $00 ; 0E SendDFAC send 1 bytes, receive 0 data bytes
|
||
dc.b $00, $02 ; 0F RunDiags send 0 bytes, receive 2 data bytes
|
||
dc.b $00, $01 ; 10 CtrlEnabSense send 0 bytes, receive 1 data bytes
|
||
; 10 BatterySense send 0 bytes, receive 1 data bytes
|
||
dc.b $00, $00 ; 11 Restart send 0 bytes, receive 0 data bytes
|
||
dc.b $01, $00 ; 12 SetVpp send 1 bytes, receive 0 data bytes
|
||
; 12 SetIPL send 1 bytes, receive 0 data bytes
|
||
dc.b $01, $00 ; 13 SetFileServer send 1 bytes, receive 0 data bytes
|
||
dc.b $01, $00 ; 14 SetAutoPoll send 1 bytes, receive 0 data bytes
|
||
dc.b $00, $02 ; 15 GetPramSize send 0 bytes, receive 2 data bytes
|
||
dc.b $00, $01 ; 16 GetAutoPollRate send 0 bytes, receive 1 data bytes
|
||
dc.b $01, $00 ; 17 SetBusDelay send 1 bytes, receive 0 data bytes
|
||
dc.b $00, $01 ; 18 GetBusDelay send 0 bytes, receive 1 data bytes
|
||
dc.b $02, $00 ; 19 SetDevList send 2 bytes, receive 0 data bytes
|
||
dc.b $00, $02 ; 1A GetDevList send 0 bytes, receive 2 data bytes
|
||
dc.b $01, $00 ; 1B SetOneSecMode send 1 bytes, receive 0 data bytes
|
||
dc.b $01, $00 ; 1C SetKbdNMI send 1 bytes, receive 0 data bytes
|
||
dc.b $01, $00 ; 1D SetPostParse send 1 bytes, receive 0 data bytes
|
||
dc.b $01, $00 ; 1E SetHangTime send 1 bytes, receive 0 data bytes
|
||
dc.b $00, $01 ; 1F GetHangTime send 0 bytes, receive 1 data bytes
|
||
dc.b $80, $00 ; 20 SendDefault DFAC send 0-4 bytes, receive 0 data bytes {?} rb
|
||
dc.b $01, $00 ; 21 Enable PDMMessage send 1 bytes, receive 0 data bytes {?} rb
|
||
dc.b $00, $00 ; 22 RdWrIIC send n bytes, receive n data bytes <S2> [rbm]
|
||
dc.b $01, $00 ; 23 Set WakeUpMode send 1 bytes, receive 0 data bytes <T2><SM7> rb
|
||
dc.b $01, $00 ; 24 Tickle PDM Timer send 1 bytes, receive 0 data bytes <T2><SM7> rb
|
||
|
||
|
||
ADBCntTable
|
||
dc.b $00, $00 ; 0000 SendReset send 0 bytes, receive 0 data bytes
|
||
dc.b $00, $00 ; 0001 Flush send 0 bytes, receive 0 data bytes
|
||
dc.b $00, $00 ; 0010 send 0 bytes, receive 0 data bytes
|
||
dc.b $00, $00 ; 0011 send 0 bytes, receive 0 data bytes
|
||
dc.b $00, $00 ; 0100 send 0 bytes, receive 0 data bytes
|
||
dc.b $00, $00 ; 0101 send 0 bytes, receive 0 data bytes
|
||
dc.b $00, $00 ; 0110 send 0 bytes, receive 0 data bytes
|
||
dc.b $00, $00 ; 0111 send 0 bytes, receive 0 data bytes
|
||
dc.b $80, $00 ; 10xx Listen send n bytes, receive 0 data bytes
|
||
dc.b $80, $00 ; 10xx Listen send n bytes, receive 0 data bytes
|
||
dc.b $80, $00 ; 10xx Listen send n bytes, receive 0 data bytes
|
||
dc.b $80, $00 ; 10xx Listen send n bytes, receive 0 data bytes
|
||
dc.b $00, $08 ; 11xx Talk send 0 bytes, receive 8 data bytes max
|
||
dc.b $00, $08 ; 11xx Talk send 0 bytes, receive 8 data bytes max
|
||
dc.b $00, $08 ; 11xx Talk send 0 bytes, receive 8 data bytes max
|
||
dc.b $00, $08 ; 11xx Talk send 0 bytes, receive 8 data bytes max
|
||
|
||
|
||
|
||
EndWith
|
||
|
||
|
||
Eject
|
||
;=========================================================================
|
||
; Routines: EgretInit
|
||
;
|
||
; This routine sends a NOP/WarmStart command to Egret. 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 Egret to initialize the
|
||
; the DFAC hardware to a known state. The routine does not use ANY
|
||
; memory it is register driven only.
|
||
;
|
||
; NOTE: This routine actually sends a STOP AUTO POLL, SET ONE SECOND
|
||
; INTERRUPT MODE 0 call and a SEND DFAC command to Egret.
|
||
; The Stop Autopoll and set one second interrupt modes calls will
|
||
; be changed to a single NOP/WarmStart when Egret 3 becomes
|
||
; available (S/B 4/6/90).
|
||
;
|
||
; Inputs: NONE
|
||
;
|
||
; Outputs: NONE
|
||
;
|
||
; Destroys: D0, D1, D2, D3, A1, A5, A6, A4 (Egret 2 implementation)
|
||
; Destroys: D0, D3, A1, A5, A6 (Egret 3 implementation)
|
||
;
|
||
; NOTE: This routine is called via a BSR6 and returns via a RTS6
|
||
;-------------------------------------------------------------------------
|
||
EXPORT EgretInit
|
||
|
||
EgretInit movea.l DecoderInfo.VIA1Addr(a0),a1 ; get VIA 1 base address
|
||
eieioSTP
|
||
bclr.b #vSyssesbit,vBufB(a1) ; kill any pending transactions <8> <13>
|
||
eieioSTP
|
||
bclr.b #vViafullbit,vBufB(a1) ; <8> <13>
|
||
eieioSTP
|
||
moveq #$28,d0 ; we want to delay 4 millisecs
|
||
@killtime bsr5 delay100us ; in 100 usec increments
|
||
dbra d0,@killtime
|
||
move.l a6,a4 ; save the return address
|
||
|
||
if rayFix then
|
||
;
|
||
; Send the Stop autopoll pseudo command
|
||
;
|
||
move.l #(APoll << 16) + PseudoPkt,d0 ; first command to send is Stop Auto Poll
|
||
moveq #0,d1 ; sending one byte of data $00 = stop autopoll
|
||
moveq #1,d2
|
||
bsr6 SendEgretCmd ; send the command to Egret
|
||
tst.w d0 ; check for an error
|
||
bne.s @exit ; failed to send the command (hang timeout expired)
|
||
;
|
||
; Send the mode 0 1 second interrupt pseudo command
|
||
;
|
||
move.l #(Wr1SecMode << 16) + PseudoPkt,d0 ; mode 0 1 sec interrupts (stop 1 second irq)
|
||
moveq #0,d1 ; sending one byte of data
|
||
moveq #1,d2
|
||
bsr6 SendEgretCmd ; send the command to Egret
|
||
tst.w d0 ; negative if error
|
||
bne.s @exit ; failed to send the command (hang timeout expired)
|
||
|
||
else
|
||
;
|
||
; Send the NOP/WarmStart command
|
||
;
|
||
move.w #NopCmd,d0 ; Nop/WarmStart stops autopoll and 1 sec irq
|
||
swap d0 ; packet type Pseudo
|
||
move.w #pseudopkt,d0
|
||
moveq #0,d2 ; no data to send
|
||
bsr6 SendEgretCmd ; send the command to Egret
|
||
tst.w d0 ; nonzero if error
|
||
bne.s @exit ; failed to send the command (hang timeout expired)
|
||
|
||
endif
|
||
|
||
;
|
||
; Send Elsie/Erickson initial DFAC setting
|
||
;
|
||
with ProductInfo
|
||
|
||
moveq #0,d2 ; force full scan of hardware features <10>
|
||
bsr6 GetHardwareInfo ; get the ProductInfo Record <9>
|
||
btst.b #v8chipbit,ExtValid+3(a1) ; See if system has a VISA chip (bit7)<9><10>
|
||
beq.s @Erickson ; 0 = No Visa (Erickson) 1 = Visa (Elsie) <9>
|
||
|
||
move.l #ElsieDFAC,d1 ; Assume running on Erickson (Not Elsie) <9>
|
||
bra.s @sendit
|
||
|
||
@Erickson move.l #EricksonDFAC,d1 ; Erickson DFAC setting <9>
|
||
@sendit move.l #(WrDFAC << 16) + PseudoPkt,d0 ; Send DFAC command
|
||
moveq #1,d2 ; One byte to send
|
||
bsr6 SendEgretCmd ; send the command to Egret
|
||
tst.w d0 ; negative if error
|
||
@exit move.l a4,a6 ; restore return address
|
||
rts6 ; return to the caller
|
||
|
||
endwith
|
||
|
||
eject
|
||
************************************************************************************************************
|
||
* SendEgretCmd: This register based routine will send up to four bytes of data to Egret. 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 Egret hung
|
||
* and the system aborted the transaction.
|
||
*
|
||
* WARNING: This routine will not error check the transaction requested. It is the responsibility of
|
||
* WARNING: the caller to make sure that the packet type, command, data and data byte count are valid
|
||
* WARNING: for the transaction requested. Failure to follow the rules will make this routine fail and
|
||
* WARNING: 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 Egret
|
||
*
|
||
* Destroys: D2.l, D3.l, D4.l, A5.l, A4.l, A1.l
|
||
*
|
||
************************************************************************************************************
|
||
|
||
Export SendEgretCmd
|
||
SendEgretCmd
|
||
movea.l DecoderInfo.VIA1Addr(a0),a1 ; get VIA 1 base address <P2> <SM7> rb, start
|
||
move.l #((MaxTout<<16) OR MaxRetries),d4 ; number of retries before giving up with Egret <13>
|
||
bsr5 Delay100us
|
||
eieioSTP
|
||
btst.b #vsysSesBit,vBufB(a1) ; check for a transaction in progress
|
||
eieioSTP
|
||
beq.s @AllOK
|
||
|
||
@Timeout
|
||
eieioSTP
|
||
bclr.b #vsysSesBit,vBufB(a1) ; kill the rest of the transaction <8>
|
||
eieioSTP
|
||
bclr.b #vViaFullBit,vBufB(a1) ; <8>
|
||
eieioSTP
|
||
bsr5 Delay100us ; in progretss <8>
|
||
bsr5 Delay100us ; <8>
|
||
|
||
@AllOK swap.w d4 ; timeout in low word of d4 Retry count in high word <13>
|
||
eieioSTP
|
||
btst.b #vxcvrSesBit,vBufB(a1) ; check for abort pending
|
||
eieioSTP
|
||
beq IrqMissed ; MIssed Vsr Irq because of INITVIAS
|
||
bset #vsysSesBit,vBufB(a1) ; assert sysSesBit
|
||
eieioSTP
|
||
bsr5 @SendPtype ; send the packet type
|
||
beq RealAbort ; Discard Aborting transaction <SM7> rb, end
|
||
;
|
||
; If not abort transaction in progress then send the command byte
|
||
;
|
||
swap d0
|
||
bsr5 sendByte1 ; send the command byte
|
||
bsr5 delay100us ; give Egret time to see viaEmpty
|
||
;
|
||
; 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
|
||
bsr5 delay100us
|
||
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
|
||
eieioSTP
|
||
bclr.b #vSyssesbit,vBufB(a1) ; negate vSyssesbit
|
||
eieioSTP
|
||
bsr5 Delay100us
|
||
;
|
||
; Now receive the Standard Response packet Header
|
||
;
|
||
bsr5 readAttn ; get the Attention byte
|
||
eieioSTP
|
||
bsr5 Delay100us
|
||
eieioSTP
|
||
bset.b #vSyssesbit,vBufB(a1) ; assert vSyssesbit
|
||
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
|
||
bclr.b #vSyssesbit,vBufB(a1) ; negate vSyssesbit
|
||
eieioSTP
|
||
bsr5 Delay100us
|
||
;
|
||
; Check for an error packet returned by Egret
|
||
;
|
||
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 ; <2>
|
||
eieioSTP
|
||
bset.b #SRdir,vACR(a1) ; shift out
|
||
eieioSTP
|
||
btst.b #vXcvrsesbit,vbufB(a1) ; check for abort
|
||
eieioSTP
|
||
beq.s @AbortReq ; go away if abort requested
|
||
move.b d0,vSR(a1) ; load byte into shift reg
|
||
eieioSTP
|
||
bset.b #vViafullbit,vBufB(a1) ; indicate shift reg is full
|
||
eieioSTP
|
||
;
|
||
; Check Vsr Irq until timeout. If timeout then check the retry count
|
||
; and Call Death Chimes if Retry count exausted.
|
||
;
|
||
@PollDelay
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a1) ; wait for shift to complete
|
||
eieioSTP
|
||
bne.s @VsrIrq ; Go service Shift register Irq <13>
|
||
dbra.w d4,@PollDelay ; try again if timed out <13><SM7> rb
|
||
move.w #MaxTout,d4 ; Reset the Timeout <13><SM7> rb
|
||
swap.w d4 ; get the Retry count <13><SM7> rb
|
||
subq.w #1,d4 ; Try again if Retry count not Exausted <13><SM7> rb
|
||
beq.s @Timeout ; <13>
|
||
|
||
@DeadEgret move.w #ErrEgretInit,d7 ; Egret failed <13>
|
||
move.l #0001,d6 ; d6.l must be nonzero <13>
|
||
bigjmp Error1Handler,a3 ; Play death chimes <13>
|
||
|
||
@VsrIrq
|
||
eieioSTP
|
||
tst.b vSR(a1) ; clear the interrupt
|
||
eieioSTP
|
||
bclr.b #vViafullbit,vBufB(a1) ; now indicate shift reg empty
|
||
eieioSTP
|
||
;
|
||
; Delay 100 usec
|
||
;
|
||
move.w #DelayCnt,d3
|
||
@wait20
|
||
eieioSTP
|
||
tst.b (a1) ; sync to VIA clock
|
||
eieioSTP
|
||
dbra d3,@wait20 ; delay at least 100 us (very rough)
|
||
eieioSTP
|
||
btst.b #vXcvrsesbit,vbufB(a1) ; check for abort
|
||
eieioSTP
|
||
@AbortReq rts5
|
||
|
||
;--------------------------------------------------------------------------
|
||
; DumpAbort 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...
|
||
|
||
RealAbort
|
||
eieioSTP
|
||
bclr.b #vSyssesbit,vBufB(a1) ; deassert system session
|
||
eieioSTP
|
||
IrqMissed bsr5 Delay100us ; Let Egret see SysSes. ≥ 125µsec
|
||
eieioSTP
|
||
bclr.b #SRdir,vACR(a1) ; shift in
|
||
eieioSTP
|
||
tst.b vSR(a1) ; discard the byte
|
||
eieioSTP
|
||
bset #vSyssesbit,vBufB(a1) ; assert vSyssesbit
|
||
eieioSTP
|
||
|
||
DumpAbort
|
||
|
||
eieioSTP
|
||
bclr #vViafullbit,vBufB(a1) ; then negate VIA full bit
|
||
eieioSTP
|
||
|
||
@loop
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a1) ; wait for shift to complete
|
||
eieioSTP
|
||
beq.s @loop
|
||
bset.b #vViafullbit,vBufB(a1) ; acknowlege byte
|
||
eieioSTP
|
||
tst.b vSR(a1) ; discard the byte
|
||
eieioSTP
|
||
;
|
||
; Delay 100 usec
|
||
;
|
||
move.w #DelayCnt,d3
|
||
@wait
|
||
eieioSTP
|
||
tst.b (a1) ; sync to VIA clock
|
||
dbra d3,@wait ; delay at least 100 us (very rough)
|
||
eieioSTP
|
||
btst.b #vXcvrsesbit,vBufB(a1) ; check for last byte
|
||
eieioSTP
|
||
beq.s DumpAbort ; Clock Tick Packets only 2 bytes
|
||
;
|
||
; Last byte was read
|
||
;
|
||
bclr #vViafullbit,vBufB(a1) ; then negate VIA full bit
|
||
eieioSTP
|
||
bclr.b #vSyssesbit,vBufB(a1) ; negate vSyssesbit
|
||
eieioSTP
|
||
bsr5 Delay100us ; delay 200 usec
|
||
bra.s SendEgretCmd ; go try sending our command again
|
||
|
||
;--------------------------------------------------------------------------
|
||
sendByte1 ; <2>
|
||
eieioSTP
|
||
bset.b #SRdir,vACR(a1) ; shift out
|
||
eieioSTP
|
||
move.b d0,vSR(a1) ; load byte into shift reg
|
||
eieioSTP
|
||
bset.b #vViafullbit,vBufB(a1) ; indicate shift reg is full
|
||
eieioSTP
|
||
@poll
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a1) ; wait for shift to complete
|
||
eieioSTP
|
||
beq.s @poll
|
||
tst.b vSR(a1) ; clear the interrupt
|
||
eieioSTP
|
||
bclr.b #vViafullbit,vBufB(a1) ; now indicate shift reg empty
|
||
eieioSTP
|
||
rts5
|
||
|
||
;--------------------------------------------------------------------------
|
||
readByte
|
||
eieioSTP
|
||
btst.b #ifSR,vIFR(a1) ; wait for shift to complete
|
||
eieioSTP
|
||
beq.s readByte
|
||
bset.b #vViafullbit,vBufB(a1) ; Tell Egret we saw the byte
|
||
eieioSTP
|
||
move.b vSR(a1),d0 ; read the byte
|
||
;
|
||
; Delay 100 usec
|
||
;
|
||
eieioSTP
|
||
move.w #DelayCnt,d3
|
||
@wait
|
||
eieioSTP
|
||
tst.b (a1) ; sync to VIA clock
|
||
eieioSTP
|
||
dbra d3,@wait ; delay at least 100 us (very rough)
|
||
eieioSTP
|
||
bclr #vViafullbit,vBufB(a1) ; then negate VIA full bit
|
||
eieioSTP
|
||
rts5
|
||
|
||
;--------------------------------------------------------------------------
|
||
readAttn
|
||
eieioSTP
|
||
|
||
btst.b #ifSR,vIFR(a1) ; wait for shift to complete
|
||
eieioSTP
|
||
beq.s readAttn
|
||
eieioSTP
|
||
tst.b vSR(a1) ; clear the interrupt
|
||
eieioSTP
|
||
rts5
|
||
|
||
;--------------------------------------------------------------------------
|
||
delay100us
|
||
move.w #DelayCnt,d3
|
||
; add.w d3,d3 ; let's make it even rougher
|
||
@wait
|
||
eieioSTP
|
||
tst.b (a1) ; sync to VIA clock
|
||
eieioSTP
|
||
dbra d3,@wait ; delay at least 100 us (very rough)
|
||
eieioSTP
|
||
rts5
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: EclipsePDMPatch
|
||
;
|
||
; Desc: Patch for ECLIPSE PowerDown Messsage Handler Install
|
||
; and PowerDown Message Enable
|
||
;_______________________________________________________________________
|
||
|
||
EXPORT EclipsePDMPatch
|
||
EclipsePDMPatch
|
||
WITH EgretPB
|
||
;
|
||
; Initialize the Eclipse PowerDown Message handler.
|
||
;
|
||
movem.l a0-a1,-(sp) ; work registers
|
||
suba.l #EgretPbSize,sp ; make room for PB
|
||
move.l sp,a0 ; point a0 to pbBuffer <T3>
|
||
move.w #(PDMVectPkt << 8),pbCmdType(a0); InitPDM Vector Packet (Cmd ignored)
|
||
clr.l pbCompletion(a0) ; No Completion
|
||
lea KeySwitchHandler,a1 ; address of keyswitch sense handling <T5>
|
||
move.l a1,PbParam(a0)
|
||
_EgretDispatch
|
||
|
||
; •••••••••••••••••••••••••••••••••••••••••••••••••
|
||
; We don't want to enable messages where we set up the Power Down Message Handler. This is because <T10>
|
||
; up until the time a system is located to boot from, when the user turns the keyswitch OFF, there <T10>
|
||
; are no files to flush, no volumes to unmount and Caboose can safely turn the machine off with us <T10>
|
||
; getting in the way. Once we get a system loaded, we'll enable Power Down Messages with the other <T10>
|
||
; routine, EclipsePDEPatch() (see below). <T10>
|
||
; •••••••••••••••••••••••••••••••••••••••••••••••••
|
||
|
||
; We need to allocate a TimeMgr TMTask record that we can use once we enable power down messages so <T15>
|
||
; we can power the machine down even if UnMounts fail or hang. ExpandMemRec has JUST been initialized <T15>
|
||
; when this patch gets called, so this is safe to do. <T15>
|
||
|
||
WITH ExpandMemRec
|
||
|
||
movea.l expandMem,a1 ; get base of ExpandMemRec <T15>
|
||
moveq.l #(tmQSize+dtQElSize),d0 ; request a TimeMgr TMTask+Deferred Task-sized record in SysHeap <T15>
|
||
_NewPtr ,SYS,CLEAR ; <T15>
|
||
move.l a0,emKeyTMTaskPtr(a1) ; save pointer to TMTask record in ExpandMemRec <T15>
|
||
ENDWITH
|
||
adda.l #EgretPbSize,sp ; discard the parameter block
|
||
movem.l (sp)+,a0-a1 ; restore registers
|
||
@EgretDone
|
||
|
||
rts ; Return to Caller
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Eclipse Keyswitch Handler
|
||
; -------------------------
|
||
;
|
||
; This routines either
|
||
; (1) turns off Eclipse, or
|
||
; (2) catches and ignores keyswitch changes interrupts
|
||
; from Caboose, since we look directly at the keyswitch
|
||
; position values on VIA2[PB][v2Keyswitch] or [v2PowerOff].
|
||
;
|
||
; As of DVT hardware, the values of these keyswitch positions
|
||
; should be available on VIA2 and no longer need to be maintained
|
||
; in SW.
|
||
;_______________________________________________________________________
|
||
;
|
||
; PowerDown Message Handler
|
||
;
|
||
export KeySwitchHandler ; <T5>
|
||
import EgretPowerOff ; from EgretPatches.a <T14>
|
||
|
||
KeySwitchHandler ; Handler of Power Down / Keyswitch Sense messages <T5>
|
||
|
||
; Caboose sends a message whenever the keyswitch sense changes. <T5> thru next <T5>
|
||
;
|
||
; Input: D0.B Keyswitch position
|
||
;
|
||
; 0 OFF
|
||
; 1 Secure
|
||
; 2 Insecure or ON ("normal")
|
||
;
|
||
|
||
tst.b d0 ; check for PowerOff message <T10>
|
||
bne.s @rts ; IF Message == PowerDOWN THEN <T10>
|
||
|
||
movem.l a0-a1,-(sp) ; save A0, A1 <T15> thru next <T15>
|
||
|
||
; First, install a time manager task that will forcefull shut us down in 5 seconds. That way,
|
||
; in case something goes wrong with the deferred task, we will shut off anyway.
|
||
|
||
WITH ExpandMemRec
|
||
|
||
movea.l expandMem,a1 ; get base address of ExpandMemRec
|
||
movea.l emKeyTMTaskPtr(a1),a0 ; retrieve "final" Time Mgr queue element
|
||
movea.l a0,a1 ; use A1 to clear the record
|
||
moveq.l #((tmQSize+dtQElSize)/2)-1,d0 ; clear the TimeMgr+DeferredTask queue elements
|
||
@clrRec clr.w (a1)+ ; just in case someone has crapped them up
|
||
dbra d0,@clrRec
|
||
lea PullThePlug,a1 ; get address of where to go when timer expires
|
||
move.l a1,tmAddr(a0) ; tell the TimeMgr about it
|
||
_InsTime ; go install the Turn Off The Power Time Mgr task
|
||
move.l #(5*1000),d0 ; set timeout to be 5 SECONDS
|
||
_PrimeTime ; activate the task
|
||
|
||
; Now install the Deferred Task that will attempt to unmount all mounted volumes.
|
||
;
|
||
; The ExpandMemRec Ptr points at an area that is tmQSize+dtQSize bytes big.
|
||
;
|
||
; Initialize the Deferred Task queue element to point at our Unmount Volumes Deferred Task.
|
||
|
||
adda.w #tmQSize,a0 ; move A0 to point at the Deferred Task Queue Element
|
||
move.w #dtQType,dtType(a0) ; and initialize the record
|
||
lea EclipseAdios,a1
|
||
move.l a1,dtAddr(a0)
|
||
jsr ([jDTInstall]) ; go install our Unmount and Shutdown deferred task
|
||
movem.l (sp)+,a0-a1 ; restore A0, A1
|
||
tst.w d0 ; see whether or not deferred task install was done
|
||
bne.s PullThePlug ; if it failed, shut down RIGHT NOW
|
||
@rts rts ; if it was successful, return to the int. handler
|
||
|
||
ENDWITH
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: EclipseAdios
|
||
;
|
||
; Desc: Deferred Task installed when the keyswitch is turned
|
||
; to the OFF position. This attempts to Unmount all
|
||
; volumes. Once that attempt has been made, the system
|
||
; is powered down.
|
||
;
|
||
; Inputs: None.
|
||
; Returns: None.
|
||
; Trashes: The System. Power to Eclipse is turned off. G'night.
|
||
;
|
||
;_______________________________________________________________________
|
||
|
||
EclipseAdios
|
||
|
||
; Try and unmount any mounted volumes before we power down.
|
||
|
||
move.l VCBQHdr+qHead,a1 ; Start at the head of the VCBQ
|
||
bra.s @checkVCB ; Check if valid
|
||
@UMloop
|
||
tst.w vcbFSID(a1) ; Make sure it’s FSID = 0
|
||
bne.s @nextQEntry ; ... i.e. not a server
|
||
|
||
; Try to unmount the volume.
|
||
|
||
sub.w #ioQElSize,a7 ; get an I/O param block
|
||
movea.l a7,a0
|
||
|
||
move.w vcbVRefNum(a1),ioVRefNum(a0) ; stuff VCB VRefNum into PB
|
||
move.l #0,ioFileName(a0)
|
||
move.l #0,ioCompletion(a0) ; no completion routine
|
||
move.l a1,-(sp) ; save A1 (queue link ptr)
|
||
_HUnmountVol ; attempt to forcefully unmount volume
|
||
movea.l (sp)+,a1 ; restore A1
|
||
adda.w #ioQElSize,a7 ; get rid of PB. we'll reallocate the PB if needed
|
||
|
||
@nextQEntry movea.l qLink(a1),a1 ; get next queue entry
|
||
@checkVCB move.l a1,d0 ; at EOQ yet?
|
||
bne.s @UMloop ; nope, try this one
|
||
|
||
PullThePlug ; ENDIF
|
||
bsr.l EgretPowerOff ; power junkies go into sudden withdrawl <T16>
|
||
bra.s PullThePlug ; with no hope of recovery <T16>
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: EclipseDFACPatch
|
||
;
|
||
; Desc: Patch for ECLIPSE send default DFAC Messsage
|
||
;_______________________________________________________________________
|
||
EXPORT EclipseDFACPatch
|
||
|
||
EclipseDFACPatch
|
||
;
|
||
; Build a Parameter block for the default DFAC message
|
||
;
|
||
movem.l a0-a1,-(sp) ; work register
|
||
suba.l #EgretPbSize,sp ; make room for PB
|
||
move.l sp,a0 ; point a0 to pbBuffer <T4>
|
||
move.w #(pseudoPkt << 8) \
|
||
+ SetDefDFAC,pbCmdType(a0) ; InitPDM Vector Packet (Cmd ignored)
|
||
clr.l pbCompletion(a0) ; No Completion
|
||
;
|
||
; Build the DFAC message issue the call and clean up
|
||
;
|
||
move.w #$0100,-(sp) ; byte count and one DFAC byte in buffer
|
||
move.l sp,pbBufPtr(a0) ; Buffer pointer
|
||
move.w #$0002,pbByteCnt(a0) ; byte count includes the byte count byte in the buffer
|
||
_EgretDispatch
|
||
adda.l #EgretPbSize+2,sp ; discard the parameter block and data buffer
|
||
movem.l (sp)+,a0-a1
|
||
@EgretDone
|
||
rts ; Return to Caller
|
||
|
||
;_______________________________________________________________________ <T16> thru next <T16>
|
||
;
|
||
; Routine: DebugUtilRunKbdPatch
|
||
;
|
||
; Desc: Checks to see if the machine we're running on has a
|
||
; keyswitch, and if so, if it's in the OFF position.
|
||
; If so, then we probably don't have any choice as to
|
||
; whether volumes can be flushed and unmounted, so we
|
||
; go directly to the PowerOff routine. Do not pass Go,
|
||
; do not collect $200. (is that 200 hex dollars?)
|
||
;
|
||
; NOTE: This handles both the DebugEnter _and_ DebugPoll cases.
|
||
;_______________________________________________________________________
|
||
|
||
EXPORT DebugUtilRunKbdPatch ; provide address to InterruptHandlers.and anyone else
|
||
DebugUtilRunKbdPatch
|
||
|
||
TestFor KeyswCabooseBit ; do we have a caboose? <21>
|
||
beq.s @justDoIt ; nope <21>
|
||
|
||
; If you made it here, you're a Caboose-flavor keyswitch.
|
||
;
|
||
; VIA2 has v2PowerOff and v2Keyswitch (SECURE mode) wired, with 0=TRUE.
|
||
|
||
move.l a1,-(sp) ; save A1 temporarily
|
||
movea.l VIA2RBV,a1 ; retrieve address of VIA2
|
||
eieioSTP
|
||
btst.b #v2PowerOff,VBufB(a1) ; is the keyswitch OFF?
|
||
eieioSTP
|
||
move.l (sp)+,a1 ; restore A1
|
||
beq.s @powerOff ; IF Keyswitch != OFF THEN
|
||
@justDoIt
|
||
bra DebugPwrMgrADBPatch2 ; check for PowerMgr stuff
|
||
@powerOff ; ELSE
|
||
bra.s PullThePlug ; administer the death blow <T16>
|
||
|
||
DebugPwrMgrADBPatch2
|
||
TestFor hwCbPwrMgr ; see if we have a power manager
|
||
beq.s @noPmgrADB ; if not, skip it
|
||
|
||
movea.l VIA,a1 ; point to the VIA
|
||
movea.l Lvl1DT+(ifCB1*4),a0 ; get the handler address
|
||
jsr (a0) ; call the interrupt handler
|
||
addq.l #4,SP ; clean up stack from bsr
|
||
movem.l (sp)+,d3/a3 ; restore registers
|
||
rts
|
||
@noPmgrADB
|
||
rts
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: EgretDFACandPDM formerly: EclipseEgretPatches <P4><MC2>
|
||
;
|
||
; Desc: Calls egret patches for Eclipse with Caboose, keyswitch
|
||
; Calls Egret patches for Anyone with Cuda, SoftPower Off
|
||
;_______________________________________________________________________
|
||
|
||
EXPORT EgretDFACandPDM
|
||
IMPORT CudaPDMPatch
|
||
|
||
EgretDFACandPDM
|
||
|
||
move.l #EgretFWMask, d0 ; get productInfo record mask for Egret FW
|
||
and.l UnivRomFlags,d0 ; isolate the field
|
||
sub.l #Caboose,d0 ; Do we have an Egret/Caboose?
|
||
bne.s @Done ; -> Nope. Don't do nothing!
|
||
|
||
; Instead of calling EclipseDFACPatch, this should more generally initialize DFAC
|
||
; for all machines that care about it (or even if we don't but it needs it anyway).
|
||
; -- bg/djw, 12/6/90
|
||
|
||
@EgretCaboose
|
||
bsr EclipseDFACPatch ; call the Eclipse DFAC control patch
|
||
bsr EclipsePDMPatch ; call the Eclipse keyswitch/PowerDown Msgs patch
|
||
@Done rts ; Return to Caller
|
||
|
||
|
||
;--------------------------------------------------------------------------
|
||
;ChkFirmware <P2>
|
||
;
|
||
; This routine will determine if the Egret Chip is using Egret 8 or Caboose
|
||
; firmware or the new Cuda firmware. Based on this result, the IRQ handler,
|
||
; Dispatcher, and Tick handler vectors are set up...
|
||
; Inputs:
|
||
; A2 -> EgretGlobals
|
||
; Outputs:
|
||
; A0 -> ShiftRegIRQ
|
||
; A1 -> TickHandler
|
||
; Trashes:
|
||
; A0,A1
|
||
|
||
|
||
ChkFirmware ; <P2>
|
||
movem.l a2/d0-d2, -(sp) ; preserve used regs
|
||
|
||
move.l #EgretFWMask,d0 ; mask for EgretFW <MC2>
|
||
and.l UnivRomFlags,d0 ; isolate the field
|
||
sub.l #Egret8,d0 ; see if we have EgretFW
|
||
beq.s @haveEgret ; set Zero flag, exit
|
||
|
||
; If we dont have Egret FW, we still might have an Caboose FW
|
||
|
||
sub.l #Egret8,d0 ; see if we have CabooseFW
|
||
beq.s @haveCaboose ; if we do, chk for Cuda
|
||
|
||
@haveCuda ;
|
||
biglea CudaDispatch, a0 ; Cuda FW dispatcher
|
||
move.l #$92,d0 ; set $92 trap
|
||
_SetTrapAddress ,NEWOS
|
||
|
||
biglea CudaShiftRegIRQ,a0 ; stuff Cuda IRQ handler in
|
||
biglea CudaTickHandler,a1 ; stuff Cuda tick handler in
|
||
bra.s @chkDone ;
|
||
|
||
@haveEgret
|
||
@haveCaboose
|
||
lea EgretDispatch, a0 ; Egret FW dispatcher
|
||
move.l #$92,d0 ; set $92 trap
|
||
_SetTrapAddress ,NEWOS ;
|
||
;
|
||
lea ShiftRegIRQ,a0 ; stuff Egret IRQ handler in
|
||
lea tickHandler,a1 ; stuff Egret tick handler in
|
||
@chkDone
|
||
movem.l (sp)+, a2/d0-d2 ; restore used regs
|
||
rts
|
||
|
||
|
||
|
||
;-------------------------------------------------------------------------- <P2>
|
||
;SendEgretCmdPatch
|
||
;
|
||
; This routine will determine if the Egret Chip is using Egret 8 or Caboose
|
||
; firmware or the new Cuda firmware. From the firmware type, determine what
|
||
; routine to use, SendEgretCmd for Egret or Caboose, and SendCudaCmd for Cuda
|
||
;
|
||
; NOTE: This routine is REGISTER based, there isn't a stack <P4>
|
||
; SendEgretCmd is called via BSR6, so must Preserve A6, as the return address <P4>
|
||
; SendEgretCmdPatch is called via a BSR5 return is in A5 <P4>
|
||
; 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
|
||
;
|
||
;-------------------------------------------------------------------------- <P2>
|
||
|
||
SendEgretCmdPatch
|
||
move.l a5, a3 ; preserve patch return addr
|
||
move.l a6, a4 ; preserve EgretInit rtn addr
|
||
bigbsr6 GetHardwareInfo,a1 ;
|
||
move.l a4, a6 ; restore EgretInitrtn addr
|
||
move.l a3, a5 ; restore patch rtn addr
|
||
moveq.l #ProductInfo.ADBMask,d0 ;mask for ADB kind <23>
|
||
and.l d1,d0 ;isolate the field <23>
|
||
subq.l #ProductInfo.ADBEgret,d0 ;see if we have Egret ADB <23>
|
||
|
||
and.l #EgretFWMask,d4 ; isolate the field
|
||
sub.l #Egret8,d4 ; see if we have Egret8 FW
|
||
beq.s @patchdone ; if we do, zero flag set
|
||
;
|
||
; If we dont have Egret FW, we still might have an Caboose
|
||
;
|
||
sub.l #Egret8,d1 ; see if we have Caboose FW
|
||
@haveEgret ; if we do, zero flag set
|
||
beq.s @patchdone ; its Egret or Caboose, just exit...
|
||
@haveCuda ;
|
||
bigjmp SendCudaCmd,a3 ; jump to Cuda Send routine
|
||
@patchdone ;
|
||
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 Egret <13>
|
||
rts5
|
||
|
||
;--------------------------------------------------------------------------
|
||
;EgretInitPatch
|
||
;
|
||
; This routine will determine if the Egret Chip is using Egret 8 or Caboose <P4>
|
||
; firmware or the new Cuda firmware. From the firmware type, determine what
|
||
; routine to use, EgretInit for Egret or Caboose, and CudaInit for Cuda
|
||
;
|
||
; NOTE: This routine is REGISTER based, there isn't a stack
|
||
; EgretInit is called via BSR6, so must Preserve A6, as the return address
|
||
; EgretInitPatch is called via a BSR5 return is in A5
|
||
;
|
||
EgretInitPatch ;
|
||
move.l a5, a3 ; preserve patch return addr
|
||
move.l a6, a4 ; preserve EgretInit rtn addr
|
||
bigbsr6 GetHardwareInfo,a1 ;
|
||
move.l a4, a6 ; restore EgretInitrtn addr
|
||
move.l a3, a5 ; restore patch rtn addr
|
||
|
||
and.l #EgretFWMask,d1 ; isolate the field
|
||
sub.l #Egret8,d1 ; see if we have Egret8 FW
|
||
beq.s @patchdone ; if we do, zero flag set
|
||
;
|
||
; If we dont have Egret FW, we still might have an Caboose
|
||
;
|
||
sub.l #Egret8,d1 ; see if we have Caboose FW
|
||
@haveEgret ; if we do, zero flag set
|
||
beq.s @patchdone ; its Egret or Caboose, just exit...
|
||
@haveCuda ;
|
||
bigjmp CudaInit,a3 ; jump to CudaInit routine in CudaMgr.a
|
||
@patchdone ;
|
||
movea.l DecoderInfo.VIA1Addr(a0),a1 ; get VIA 1 base address
|
||
eieioSTP
|
||
bclr.b #vsysSesBit,vBufB(a1) ; kill any pending transactions <8> <13> <P2>
|
||
eieioSTP
|
||
bclr.b #vViaFullBit,vBufB(a1) ; <8> <13> <P4>
|
||
eieioSTP
|
||
rts5
|
||
|
||
TerrorEgret
|
||
|
||
IMPORT ExplicitRequestDone, ImplicitRequestDone
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: StartReqEgret
|
||
; Inputs: D2 - length of transmit buffer data
|
||
; D3 - command byte / implicit flag (bit 31)
|
||
; A2 - pointer to buffer containing transmit data
|
||
; A3 - pointer to ADBBase
|
||
;
|
||
; Outputs: A3 - pointer to ADBBase
|
||
;
|
||
; Destroys: A0-A2/D0-D2
|
||
; Calls: exits through _EgretDispatch
|
||
;
|
||
; Function: Sends an ADB request to the Egret, and asynchronously waits for a reply.
|
||
;
|
||
;_______________________________________________________________________
|
||
|
||
with ADBVars,EgretPB
|
||
|
||
|
||
jEgretDispatch equ OSTable+($92*4) ; OS trap table entry for _EgretDispatch
|
||
|
||
StartReqEgret
|
||
tst.l d3 ; see if explicit/implicit
|
||
bmi.s @implicit ; if implicit, we generally don't need to do anything
|
||
|
||
;_______________________________________________________________________
|
||
; Process Explicit Requests
|
||
|
||
@explicit bset.b #fDBExpRunning,fDBAuFlag(a3); explicit command starting, exclude new ones
|
||
bne.s @ignoreExplicit ; if already in progress, don't run it twice
|
||
move.b d3,ExplicitEPB.pbCmd(a3) ; setup the ADB command
|
||
move.w d2,ExplicitEPB.pbByteCnt(a3); setup byte count
|
||
move.l a2,ExplicitEPB.pbBufPtr(a3) ; setup buffer pointer
|
||
|
||
bset.b #fDBExpInited,fDBAuFlag(a3) ; see if explicit command initialization has occured
|
||
bne.s @expInited ; if already inited, no need to change anything
|
||
|
||
lea @ExplicitCompleted,a0 ; explicit request completion routine address
|
||
move.l a0,ExplicitEPB.pbCompletion(a3) ; setup buffer pointer
|
||
|
||
lea ImplicitEPB(a3),a0 ; point to the param block used to wait for autopoll data
|
||
clr.l pbCompletion(a0) ; remove the handler
|
||
bsr.s @SendToEgret ; remove the auto poll handler
|
||
|
||
move.l #(pseudoPkt<<24)\ ; pcCmdType := pseudoPkt
|
||
+(aPoll<<16)\ ; pbCmd := aPoll
|
||
+($00<<8),d0 ; pbParam := $00 (only high byte is used)
|
||
bsr.s @syncReq ; send command to stop auto polling
|
||
@expInited
|
||
|
||
lea ExplicitEPB(a3),a0 ; point to the param block
|
||
@SendToEgret
|
||
moveq.l #0,d1 ; zero the trapword flag bits (in case they ever get used)
|
||
movea.l jEgretDispatch,a2 ; get the OSTrap table entry
|
||
jmp (a2) ; _EgretDispatch, issue the request (asynchronously), return
|
||
|
||
|
||
;_______________________________________________________________________
|
||
; Process Implicit Requests
|
||
|
||
@implicit btst.b #fDBInit,fDBFlag(a3); see if initialization is happening
|
||
bne.s @impDone ; if so, implicit commands are ignored
|
||
bset.b #fDBImpInited,fDBAuFlag(a3) ; see if implicit command initialization has occured
|
||
beq.s @InitImplicit ; if not inited, do initialization to allow autopolling
|
||
@ignoreExplicit
|
||
@impDone rts ; auto-polling/srq data will arrive unsolicited from now on
|
||
|
||
@InitImplicit
|
||
lea ImplicitEPB(a3),a0 ; point to the param block used to wait for autopoll data
|
||
lea @ImplicitCompleted,a1 ; handler address
|
||
move.l a1,pbCompletion(a0) ; install the handler
|
||
bsr.s @SendToEgret ; install the auto poll handler
|
||
|
||
move.l #(pseudoPkt<<24)\ ; pcCmdType := pseudoPkt
|
||
+(wrDevList<<16),d0 ; pbCmd := wrDevList
|
||
move.w DevMap(a3),d0 ; pbParam := DevMap (in first 2 bytes)
|
||
bsr.s @syncReq ; send command to specify auto polling addresses
|
||
|
||
move.l #(pseudoPkt<<24)\ ; pcCmdType := pseudoPkt
|
||
+(aPoll<<16)\ ; pbCmd := aPoll
|
||
+($FF<<8),d0 ; pbParam := $FF (only high byte is used)
|
||
; send command to start auto polling
|
||
|
||
@syncReq suba.w #EgretPBSize,sp ; allocate a param block on the stack for a sync call
|
||
movea.l sp,a0 ; point to the param block
|
||
move.l d0,pbCmdType(a0) ; init pcCmdType, pbCmd, and high word of pbParam
|
||
clr.l pbCompletion(a0) ; no completion routine, sync call
|
||
bsr.s @SendToEgret ; call send the request off to the ADB micro
|
||
adda.w #EgretPBSize,sp ; deallocate the param block
|
||
rts ; auto-polling/srq data will arrive unsolicited from now on
|
||
Title 'KbdADB - ADB Manager - ExplicitCompleted'
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: @ExplicitCompleted
|
||
; Inputs: A0 - Pointer to the EgretPB of the Explicit Request
|
||
;
|
||
; Outputs: D2 - length of receive buffer data
|
||
; D3 - command byte / SRQ flag (bit 31)
|
||
; A2 - pointer to buffer containing receive data
|
||
; A3 - pointer to ADBBase
|
||
;
|
||
; Calls: exits through ImplicitRequestDone / ExplicitRequestDone
|
||
; Called by: Egret Manager, Asynchronous request completion routine
|
||
;
|
||
; Function: Completion routine for servicing explicit ADB requests.
|
||
;
|
||
;_______________________________________________________________________
|
||
|
||
@ExplicitCompleted ; A0 := pointer to EgretPB
|
||
if EgretDebug then
|
||
btst.b #EgAutoPoll,pbFlags(a0) ; see if this was from auto poll
|
||
beq.s @ExplicitOK ; if not, we're still OK
|
||
_Debugger ; something is wrong with this picture
|
||
@ExplicitOK
|
||
endif
|
||
moveq.l #(1<<EgSRQ),d3 ; mask to test for SRQ pending
|
||
and.b pbFlags(a0),d3 ; isolate the SRQ flag
|
||
neg.l d3 ; set bit 31 if SRQ pending
|
||
move.b pbCmd(a0),d3 ; get the ADB command byte
|
||
moveq #0,d2 ; zero extend the length
|
||
move.w pbByteCnt(a0),d2 ; get the length
|
||
movea.l pbBufPtr(a0),a2 ; get the buffer pointer
|
||
bsr.s @FillInVars ; setup A3, and ADB globals for ADB Parser
|
||
bclr.b #fDBExpRunning,fDBAuFlag(a3) ; explicit command completed, allow new ones
|
||
|
||
;
|
||
; For Egret must check the ADB Device address against the Device Bitmap <5>
|
||
; to see if the device exists. If it does not, force Egret to Poll the Mouse
|
||
; as the MRU device and Keyboard as the LRU device. (Bug Fix for Egret)
|
||
;
|
||
; Entry: a3.l = ADB Globals
|
||
; d0.b = ADB device address
|
||
|
||
move.w devmap(a3),d1 ; get the ADB device Bitmap
|
||
btst.l d0,d1 ; check bit position in low word
|
||
bne.s @exit ; Device Exits
|
||
|
||
;------------------------------------------------------------------------------
|
||
; Force the MRU & LRU values to Mouse & Keyboard to work around bug where Egret
|
||
; AutoPolls devices which are not in the DevMap.
|
||
;
|
||
; Entry: NONE
|
||
;
|
||
; Exit: NONE
|
||
;
|
||
; Destroys: NONE
|
||
;
|
||
;------------------------------------------------------------------------------
|
||
|
||
suba.l #EgretPbSize,sp ; make room for Egret Manager PB
|
||
movea.l sp,a0
|
||
move.l #0,pbCompletion(a0) ; no Completion vector
|
||
move.w #((pseudoPkt << 8) + \
|
||
Wr6805addr),pbCmdType(a0) ; packet type & command
|
||
move.w #((MouseAddr * $1000) + \ ; Mouse & Keyboard into MRU & LRU
|
||
(KbdAddr * $10)),-(sp) ; Mouse Addr in bits C-F, Kbd Addr bits 4-7
|
||
move.l sp,pbBufPtr(a0) ; buffer pointer in PB
|
||
move.w #MRUAddr,pbParam(a0) ; Egret address to write
|
||
move.w #2,pbByteCnt(a0) ; 2 bytes to write
|
||
_EgretDispatch ; issue the call
|
||
adda.l #EgretPbSize+2,sp ; Discard Buffer & Parameter block <5>
|
||
|
||
@exit
|
||
bigjmp ExplicitRequestDone,a0 ; Return control to the ADB Manager
|
||
|
||
@FillInVars movea.l ADBBase,a3 ; point to ADB globals in low memory
|
||
|
||
; keep the ADB Parser program happy by updating the following variables
|
||
; They are not used by this implementation, but we fill them in with approximate
|
||
; values to make the tool happy.
|
||
|
||
move.b d3,fDBCmd(a3) ; last ADB command
|
||
move.b d3,pollCmd(a3) ; assume that it was a poll command
|
||
move.b d3,d0 ; copy the command
|
||
lsr.b #4,d0 ; get the address
|
||
move.b d0,pollAddr(a3) ; assume that it was a poll address
|
||
rts ; all done
|
||
Title 'KbdADB - ADB Manager - ImplicitCompleted'
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: @ImplicitCompleted
|
||
; Inputs: A0 - Pointer to the EgretPB of the Implicit Request
|
||
; D0 - Number of data bytes returned (word, 0..8)
|
||
; A1 - Pointer to Flags, Command, Data Buffer
|
||
;
|
||
; Outputs: D2 - length of receive buffer data
|
||
; D3 - command byte / SRQ flag (bit 31)
|
||
; A2 - pointer to buffer containing receive data
|
||
; A3 - pointer to ADBBase
|
||
;
|
||
; Calls: exits through ImplicitRequestDone / ExplicitRequestDone
|
||
; Called by: Egret Manager, Asynchronous request completion routine
|
||
;
|
||
; Function: Completion routine for servicing explicit ADB requests.
|
||
;
|
||
;_______________________________________________________________________
|
||
|
||
@ImplicitCompleted
|
||
if EgretDebug then
|
||
btst.b #EgAutoPoll,(a1) ; see if this was from auto poll
|
||
bne.s @ImplicitOK ; if so, we're still OK
|
||
_Debugger ; something is wrong with this picture
|
||
@ImplicitOK
|
||
endif
|
||
moveq.l #(1<<EgSRQ),d3 ; mask to test for SRQ pending
|
||
and.b (a1)+,d3 ; isolate the SRQ flag
|
||
neg.l d3 ; set bit 31 if SRQ pending
|
||
move.b (a1)+,d3 ; get the ADB command byte
|
||
moveq #0,d2 ; zero extend the length
|
||
move.w d0,d2 ; get the length
|
||
movea.l a1,a2 ; get the buffer pointer
|
||
bsr.s @FillInVars ; setup A3, and ADB globals for ADB Parser
|
||
bigjmp ImplicitRequestDone,a0 ; Return control to the ADB Manager
|
||
endwith
|
||
|
||
|
||
|
||
Export DebugEnterCont
|
||
|
||
DebugEnterCont
|
||
with ProductInfo
|
||
|
||
move.l UnivRomFlags,d0 ; get the Universal system flags
|
||
andi.l #ADBMask,d0 ; we want ADB
|
||
cmpi.l #ADBEgret,d0 ; and specifically EGRET version of ADB
|
||
bne.s @EgretDone
|
||
|
||
endwith
|
||
|
||
;
|
||
; Build a Egret Parameter block to stop 1 second interrupts
|
||
;
|
||
WITH EgretPb
|
||
move.l a0,-(sp) ; work registers
|
||
suba.l #EgretPB.EgretPbSize,sp ; room for parameter block
|
||
move.l sp,a0 ; point to the parameter block
|
||
move.w #(EgretPB.EgretPBSize/2)-1,d0 ; clear the PB area a word at a time
|
||
|
||
move.l a0,-(sp) ; save pointer to parameter block
|
||
@Loop move.w #0,(a0)+ ; zeros forces mode 0 & no Completion vector
|
||
dbra d0,@Loop
|
||
move.l (sp)+,a0 ; restore parameter block pointer
|
||
|
||
move.w #((pseudoPkt << 8) + Wr1SecMode),EgretPB.pbCmdType(a0) ; Packet type & command
|
||
_EgretDispatch
|
||
;
|
||
; Suspend the PDM, with out reseting vars within Cuda
|
||
;
|
||
move.w #(PseudoPkt << 8) \
|
||
+ EnDisPDM,pbCmdType(a0); Enable PowerDown Messages <P3>
|
||
clr.l pbParam(a0) ; clr parameter blk <P3>
|
||
move.b #PDMSuspend,pbParam(a0) ; PDM Continue <P3>
|
||
clr.l pbCompletion(a0) ; No Completion <P3>
|
||
; _EgretDispatch <SM11> gjs
|
||
|
||
adda.l #EgretPB.EgretPbSize,sp ; discard parameter block
|
||
move.l (sp)+,a0 ; restore work registers
|
||
ENDWITH
|
||
@EgretDone
|
||
|
||
moveq.l #noErr,d0 ; return with success
|
||
rts
|
||
|
||
;••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
|
||
|
||
Export DebugExitCont
|
||
|
||
DebugExitCont
|
||
with ProductInfo
|
||
|
||
move.l UnivRomFlags,d0 ; get the Universal system flags
|
||
andi.l #ADBMask,d0 ; we want ADB
|
||
cmpi.l #ADBEgret,d0 ; and specifically EGRET version of ADB
|
||
bne.s @EgretDone
|
||
|
||
endwith
|
||
|
||
;
|
||
; Build a Egret Parameter block to start 1 second interrupts (Mode 3)
|
||
;
|
||
WITH EgretPB
|
||
move.l a0,-(sp) ; work registers
|
||
suba.l #EgretPB.EgretPbSize,sp ; room for parameter block
|
||
move.l sp,a0 ; point to the parameter block
|
||
move.w #(EgretPB.EgretPBSize/2)-1,d0 ; clear the PB area a word at a time
|
||
|
||
move.l a0,-(sp) ; save pointer to parameter block
|
||
@Loop move.w #0,(a0)+ ; zeros forces mode 0 & no Completion vector
|
||
dbra d0,@Loop
|
||
move.l (sp)+,a0 ; restore parameter block pointer
|
||
move.w #((pseudoPkt << 8) + Wr1SecMode),EgretPB.pbCmdType(a0) ; Packet type & command
|
||
move.b #Mode3Clock,EgretPB.pbParam(a0) ; Turn on Mode 3 clock data packets
|
||
_EgretDispatch
|
||
;
|
||
; Macsbug Continue the PDM
|
||
;
|
||
move.w #(PseudoPkt << 8) \
|
||
+ EnDisPDM,pbCmdType(a0); Enable PowerDown Messages <P3>
|
||
clr.l pbParam(a0) ; clr parameter blk <P3>
|
||
move.b #PDMDebugCont,pbParam(a0) ; Macsbug Continue <SM11> gjs <P3>
|
||
clr.l pbCompletion(a0) ; No Completion <P3>
|
||
_EgretDispatch
|
||
|
||
adda.l #EgretPB.EgretPbSize,sp ; discard parameter block
|
||
move.l (sp)+,a0 ; restore work registers
|
||
@EgretDone
|
||
ENDWITH
|
||
moveq.l #noErr,d0 ; return with success
|
||
CLR.B DSWndUpdate ; flag GNE to remove the alert . . . just in case <SM11> gjs
|
||
rts
|
||
|
||
ENDP
|
||
END |