supermario/base/SuperMarioProj.1994-02-09/OS/InterruptHandlers.a

3134 lines
136 KiB
Plaintext
Raw Normal View History

2019-06-29 15:17:50 +00:00
;
; File: InterruptHandlers.a
;
; Contains: This module contains the receivers for all 68000-family auto-vectored
; interrupts. It decodes the interrupt source and calls the associated
; interrupt handler. A PowerPC Macintosh may run this code in emulation.
;
; Written by: Bud Tribble
; Re-written by: Gary G. Davidian 5-Mar-89
;
; Copyright: © 1981-1994 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <SM63> 1/11/94 GS Enabled NMI in Grand Central on TNT.
; <SM61> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
; machines.
; <SM60> 11/19/93 chp Reflect macro API change in GrandCentralPriv, change some word
; branches to byte branches, and update SCSI IE primitives to work
; with both Grand Central SCSI buses. (see also: <SMG7-8>)
; <SM59> 11/10/93 fau Update from SuperMunggio <SMG2-9>. Also, addeb back KW's <SM56>
; checkin.
; <SMG9> 10/20/93 fau Enabled the PowerOff and One-secs interrupts for GrandCentral.
; <SMG8> 9/22/93 chp The Grand Central interrupt handler registration macros
; underwent an interface change.
; <SMG7> 9/13/93 chp Enable VIA interrupts after initializing the interrupt
; dispatcher, and enable only SCSI0 interrupts for the time being.
; <SMG3> 8/26/93 chp Use the provided interrupt dispatch table maintenance macros in
; within the Grand Central interrupt initialization postproc.
; <SMG2> 8/25/93 chp Introduce Grand Central support for TNT.
; <SM58> 11/10/93 rab Added semicolon to last checkin comment <MC5> so the build
; wouldn't barf…
; <SM57> 11/10/93 SAM Roll in <MC5> from mc900ftjesus.
; <MC5> 11/10/93 SAM Disable sound in/out DMA in AMICInitPostProc.
; <SM56> 11/9/93 KW added some eieioSTP macros. Only expands for CygnusX1 ROM
; <SM55> 10/29/93 pdw Moved intRegs and intRegsSize out of here and into
; SysPrivateEqu.a since SCSI Manager 4.3 is now using them.
; <SM54> 10/14/93 pdw Saving and restoring interrupt level around calls to 2nd-level
; interrupt handlers dispatched from AMIC DMA dispatch routine
; because somebody isn't restoring it themselves.
; <SM53> 9/25/93 SAM Changed the conditional around AMICIntTbl from hasAMIC to hasHMC
; because the only code the references it is in UniversalTables.a
; and that code is (rightly so) conitionalized with hasHMC.
; <SM52> 9/10/93 pdw Pulled the SCC Level 4 interrupt vectors and refcons out of the
; DMA Dispatch table (just like the maceVector).
; <SM51> 9/9/93 pdw Removed some leftover 24-bit support. Rearranged basic interrupt
; handling mechanism - no more jump islands, no more ServiceInt,
; now new FinishInt. Check it out.
; <SMG5> 9/1/93 chp When initializing PDM serial handlers, index into the table
; instead of hard-coding table offsets. When decoding serial
; interrupts, use a symbolic constant rather than a literal (per
; changes in DMADispGlobals).
; <SMG4> 8/30/93 chp Created a level 3 handler for PDM so MACE interrupts are
; processed symmetrically. Updated AMICInitPostProc to work with
; the slightly larger dispatch table.
; <SM49> 9/2/93 SKH StdVIA2DT always needs to be defined, because the universal code
; needs it.
; <SM48> 8/21/93 chp Reduced the PDMDMAHndlr instruction count by 30%.
; <SM47> 8/20/93 chp Clean up and somewhat reorganize the entire file. The 24/32 bit
; interrupt dispatcher paths are better integrated and the PSC
; interrupt dispatchers are now fully integrated into the same
; path. Bits and pieces from all over have been collected to
; reside closely with related functions. AMIC interrupt handlers
; have been slightly modified to use the standard install and
; dispatch mechanisms that everyone else uses. Some names changed
; for consistency and descriptiveness, particularly in the PSC
; code.
; <SM46> 8/2/93 pdw Changed first entry in SCSI speed table from 30MHz to 25MHz so
; that anything in the range 26 through 30 will use a value of 2
; instead of 3. This is in accordance with the timing provided by
; Jimmy.
; <SM45> 8/1/93 pdw Fixed Sam's 66/33-with-HDT-on-Eagle problem by changing the
; 33MHz entry in the SCSI handshaking table to 30, causing a 33 to
; use the value 2 instead of 3.
; <SM44> 8/1/93 pdw Fixed 50/50 AMIC/SCSI problem by avoiding the dangerous SCSI
; speed value of 3 (11 in 2 speed bits).
; <SM43> 7/19/93 pdw Added blocking of interrupts before testing DTskQHdr for
; presence of deferred tasks. Fixes a bug where you can drop to
; level 0 without executing deferred tasks.
; <SM42> 7/1/93 KW Roll in from LW. In PSCInitPostProc took out installation of
; muni nubus control int. handler. Also removed MuniVia2Int
; <SM41> 6/14/93 kc Roll in Ludwig.
; <SM40> 6/2/93 GMR Added separate interrupt table for PDM, so we can have our own
; Disable routine to turn off level 3 (Mace) interrupts. Also,
; change PDM's level 4 handler (DMA,SCC) to loop until all bits
; are clear, since the AMIC is set to interrupt on change only.
; <SM39> 5/25/93 SAM Added some Supports24Bit condos around ServiceIntMMU.
; <SM38> 5/24/93 joe PDM DMA int handler now calls ServiceIntMMU so deferred tasks
; will be run. Conditionalized 24-bit case out of ServiceIntMMU
; for PDM & Smurf.
; <SM37> 4/23/93 SAM Added a bunch of code to PDMDmaInstall. Each channel is reset
; at install timeand AMIC is now configured for the I/O bus speed
; of the machine we're on.
; <SM36> 4/22/93 CSS Changed emDMADispGlobs to emDMADispatchGlobals which matches
; Reality.
; <SM35> 4/11/93 chp Removed conditional assembly for Time Manager VBL emulation and
; instituted a runtime check in Enable60HzInts based on
; ProductInfo. Also rolled in various updates to the PSC interrupt
; handlers.
; <SM34> 4/5/93 RC Changed the DMA interrupts to Level 4 on PDM and added the SCC
; interrupt handleing to the DMA handler.
; <SM33> 4/2/93 GMR Added a couple of nop's to PDMDMAHndlr to synchronize I/O.
; <SM32> 4/1/93 GMR Moved PDM's DMA stuff from StartInit to here, where it belongs.
; <SM31> 2/25/93 RB Removed the call to WaitFloppyEject from PowerOff since this is
; now handled more elegantly in ShutDown.a. Renamed the
; WaitFloppyEject code to WaitAWhile and moved it into
; EgretPowerOff since it's still used there.
; <SM30> 1/20/93 PN Bring over the fix for PSCL5Interrupt from Ludwig where A4 value
; is trashed after 1st time through the loop.
; <SM29> 12/18/92 RB Swapped an entry on the port A interrupt handlers for the SCC in
; StdLvl12DT. This prevents the machines from freezing when the
; serial port is used.
; <SM28> 12/11/92 chp Optimized PSC interrupt dispatchers. Moved SCCA interrupt
; priority ahead of SCCB since this is the prioritization used by
; the SCC itself (see also SM10). Fixed a bug which most of the
; time prevented interrupt flags from being rechecked as intended
; (see also SM17).
; <SM27> 12/11/92 SWC Moved the rest of the Cyclone interrupt initialization stuff
; here from StartInit.a and added a general "post proc" routine to
; InitIntHandler to do any special-case initialization that can't
; be driven from just a table.
; <SM26> 12/1/92 EH Added interrupt table for Pratt.
; <SM25> 12/1/92 SWC Rewrote much of the file to do interrupt enable/disable and
; vector initialization based on tables attached to a machine's
; ProductInfo. This should make it much easier to follow what's
; going on. Added in build conditionals. Moved really old CPU
; support to the end of the file where it's conditionalized out
; with an "IF 0 THEN".
; <SM24> 11/20/92 fau Added a MUNI interrupt handler for Cyclone.
; <SM23> 11/16/92 rab Roll in Horror changes (see H7 comments below)
; <SM22> 11/4/92 fau Backed out change in <SM19> 'cause we found what the real
; culprit was (somebody writing to a ROM address that was at that
; table!)
; <SM21> 11/3/92 RB Do not "fall-into" ServiceIntMMU, since that defeats automatic
; vector patching schemes.
; <SM20> 11/3/92 SWC Changed ShutdownEqu.a->Shutdown.a.
; <SM19> 11/3/92 fau Moved the Via1Int/Via2Int Secondary interrupt dispatcher table
; further into the file to avoid an obscure data cache corruption
; problem (as far as we can tell) on a Q900/950. Changed the
; addressing mode to load values from this table to use 32-bit
; displacements.
; <SM18> 10/21/92 fau Changed all MMCExists to PSCExists.
; <SM17> 10/7/92 mal Changed Cyclone L3,4,5,6 interrupt dispatchers to check for a
; "later" interrupt.
; <SM16> 9/28/92 RB Fix PowerOff on Quadra 900 & 950 by updating the Egret check in
; the PowerOff trap.
; <SM15> 9/10/92 AEK Add support for 60.15 Hz pseudo-VBL interrupts (ala IIfx)
; Removed OSS 60Hz interrupt enable code (interrupt should never be enabled)
; Note: should be build-time selectable (currently set to non-HW vbl)
; <SM14> 8/26/92 kc Fix compiler warning.
; <SM13> 8/24/92 PN Take out checkEVT1 code
; <SM12> 8/17/92 CCH Changed “TestFor” of OrwellExists to OrwellDecoder.
; <H7> 8/4/92 SWC Increased the floppy eject delay in PowerOff from 0.5 seconds to
; 1.5 seconds to support the slower drives used in the PowerBooks.
; With the shorter delay, the disk was ejected correctly, but the
; eject mechanism was left in an in-between state when the power
; goes off. This could potentially have reliability repercussions.
; <SM11> 6/30/92 kc Rename EclipseVia2SlotInt to DAFBVia2SlotInt. Move SlotInterrupt
; handlers from InterruptHandlers.a.
; <SM10> 6/22/92 mal Changed priority of PSCL4Interrupt to SCCB, SCCA, Sound, then
; DMA ints.
; <SM9> 6/21/92 PN Rollin PatchIIciROM.a and fix the through put problem on Apollo
; and TimLC
; <SM8> 6/21/92 RB Added temporary checks for the EVT1 Cyclone boxflag to handle
; EVT1 boards. The EVT1 support will be deleted later, after all
; systems have been upgraded to EVT2.
; <SM7> 6/20/92 mal (RB) Made ASC routines do nothing on Cyclone.
; <SM6> 5/28/92 RB When I rolled in Cyclone, I forgot to add one more patch rollin
; from Horror. So it is now in.
; <SM5> 5/24/92 RB Added PSC interrupt handlers from the Pandora file
; InterruptHandlersPatch.a PSCLxDispatch routines.
; <SM4> 5/24/92 RB Making Cyclone changes...Pandora history is below. Removed
; support for 4Square and cleaned up a little bit. Patches were
; rolled in inline.
; <SM3> 5/17/92 kc Include PowerPrivEqu.a and add "pmCommandRec."
; <P8> 4/24/92 KW (SWC,H6) Modified DebugUtil to use the new ADB/DebugUtil primitives.
; Moved EnableSCSIIntsPatch here from PwrControlsPatches.a since this
; is where it's used anyway.
; <P7> 2/19/92 chp (JC,H5) Add support for level 3 interrupt for Sonic on Sonora based
; machines. On Mac II class machines, level 3 interrupt was previously
; unused.
; <SM2> 2/11/92 RB Need to add code for debugger support on the Quadras. Also
; removed dead code that used to diferentiate Eclipse from the
; rest so it could enable SCSI using CA2 instead of CB2. Eclipse
; eventually changed so that CB2 is SCSI.
; <P6> 2/11/92 GS Add patch in Power Switch Int handler to enable Soft Power Off. Patch
; code (PowerSwitchIntPatch) is located in EgretPatchesToo.a.
; <P5> 2/7/92 mal Updated references to RBV VIA2 IER & IFR to PSC VIA2 IER & IFR offsets.
; <P4> 1/24/92 mal Added PSCIntInstall back in. Changed DisableIntSources to use correct
; VIA2 IER offset for Cyclone.
; <P3> 1/22/92 RMP (for mal) Commented PSCINTINSTALL out.
; <P2> 1/21/92 mal Added patches to support PSC interrupt dispatchers for levels 3,4,5,&6.
; <H4> 12/20/91 JC Use common Via2/RBV offset equates.
; <H3> 8/13/91 SWC Fixed the revision numbers in the comments to reflect the HORROR
; numbering scheme instead of my own.
; <H2> 8/8/91 SWC Patched EnableSCSIInts so that SCSI interrupts won't be enabled
; on DB-Lite.
; <18> 10/29/91 SAM Removed several branch to next instruction that resulted from
; the removal of conditionals in the previous rev.
; <17> 10/18/91 JSM Get rid of all the stupid conditionals. This turned up several
; instances of two RTS instructions in a row, but I left these
; alone to make comparing objects easier until we merge in new ROM
; sources.
; <16> 10/1/91 JSM Dont use hasADB conditional, all future ROMs will support ADB.
; <15> 8/30/91 JSM Cleanup header.
; <14> 6/12/91 LN removed #include 'HardwareEqu.a'
; <13> 9/14/90 MSH Power off feature changed on TIM, requiring a new call to the
; power manager.
; <12> 8/8/90 BG Changed some assembly-time checks to run-time for handling
; Eclipse and non-Eclipse VIA2 interrupts.
; <11> 6/18/90 CCH Changed onEclipse conditional to hasEclipseVIA2.
; <10> 4/5/90 HJR Fix HcMac build by exporting Poweroff to HcMac builds.
; <9> 3/29/90 MSH Move PowerOff call from PowerMgr to here.
; <8> 3/22/90 GA Removing the bsr to EgretShutdown. Now, this function is
; performed by the diagnostics calling EgretMgr.
; <7> 2/28/90 GA Modified the 1 sec interrupts enable for Egret and the System
; PowerOff support to conform with the new Egret Manager Parameter
; block model.
; <6> 2/21/90 CCH Added a missing endif.
; <5> 2/19/90 BG Modified the SlotMgr VIA2 interrupt handler installer to know
; the difference between a hasMac2Via2 and a hasEclipseVIA2. Also
; added hasEclipseVIA2 to the PowerOff handling code. Added code
; to handle both 4Square and Eclipse when installing and handling
; SWIMIOP interrupts.
; <4> 2/14/90 GA Added PowerOff support for Egret. It issues a Power off command
; to Egret to turn off Erickson...
; <3> 2/12/90 BG Added interrupt handling for Eclipse.
; <2> 1/11/90 CCH Adding include of “HardwarePrivateEqu.a”.
; <3.2> 11/28/89 SWC Removed OssADB interrupt handling code.
; <3.1> 11/19/89 GGD NEEDED FOR ZONE-5. Fixed the Level 1 OSS interrupt handler to
; check the OSS mask before calling the SWIM IOP interrupt handler
; to correct a bug that only occurs during a small window in
; StartInit when SWIM IOP interrupts are masked.
; <3.0> 11/15/89 GMR NEEDED FOR ZONE-5. Added routine to enable RPU interrupts
; through the OSS.
; <2.9> 10/28/89 GGD NEEDED FOR ZONE-5. Fixed bug in Level 2 OSS interrupt handler
; when SCSI or Sound interrupts were masked, other level 2
; interrupt handlers might not have gotten called.
; <2.8> 7/15/89 GGD Added alignment of all interrupt handler entry points for better
; cache/burst performance.
; <2.7> 7/12/89 GGD Added conditionals around the overpatch padding so that it can
; be easily located.
; <2.6> 6/23/89 GGD Added optimization when running a 32 bit OS, to not call
; SwapMMUMode in the Int handlers Changed DebugUtil keyboard
; polling for IOP ADB systems to always call the interrupt handler
; and not bother checking the interrupt status. This eliminates
; problems with hangs in MacsBug, which are really caused by
; MacsBug not calling the DebugUtil Enter function, but fixing it
; in ROM makes it more robust, and is ALOT EASIER THAN TRYING TO
; GET MacsBug TO CHANGE. Added some padding to allow expansion
; space for F19 overpatch. Needed for AURORA and F19 ROMS.
; <2.5> 6/10/89 GGD Added code review changes, deleted power off (level 6) handler
; for all machines except the Mac II, since only Mac II generates
; the interrupt, to prevent power off if spurious level 6 int
; occured.
; <2.4> 5/29/89 GGD Added runtime test to DebugUtil to check for the various forms
; of ADB.
; <2.3> 5/20/89 GGD Changed a few label names related to IOP interrupt processing.
; <2.2> 4/30/89 GGD Major source modifications to make it universal, added several
; new routines to enable/disable interrupt sources. Much of the
; new code is conditional, making this code even harder to read.
; <2.1> 4/19/89 GGD Changed the OSS level 2 int handler to check the mask regs for
; SCSI and ASC, and not call the handler if masked.
; <2.0> 4/16/89 GGD Implemented DebugUtil keyboard polling for all machines.
; <1.9> 4/13/89 GGD Changed OSS interrupt handlers to use same priority as the Mac
; II for compatibility. Updated to use new names for OSS interrupt
; flags from HardwareEqu. Changed to get Base addresses from
; lowmem, instead of using absolute addresses.
; <1.8> 4/7/89 MSH Removed HcSoundHack.
; <1.7> 3/6/89 GGD Completely re-written, restructured, and optimized. Old change
; histories kept for historical purposes only. restructured to
; eliminate need to branch back to DoneInts (rts instead), to
; localize mmu/pmgr/dtask code in one place. Added Deferred Task
; Mgr to onMacPP. Changed to use more feature based conditionals.
; Move the InitXVectTables routine from StartInit to here, and
; renamed it InitIntHandler. Moved OneSecInt handler to Clock.a
; Moved SlotVBLInt to VerticalRetraceMgr.a Moved 60Hz handler to
; VerticalRetraceMgr.a Moved Slot Interrupt handler to
; SlotInterrupts.a Always setup the level 1 dispatch table entry
; for the VBLint, even on OSS based systems. On OSS systems,
; dispatch to the VBLint handler through the dispatch table with
; A1 pointing to OSS60HzAck-VIFR, so that the standard VBLint
; handler can be used unmodified, and can be patched more easily.
; Eliminated unused include files. Changed RBV register usage now
; that equates are offsets from RBVBase, instead of being absolute
; addresses. Changed OSS int handlers to dispatch through the Via1
; or Via2 dispatch tables using entries that are in common with
; other systems. Added a hack for HcMac so that the ASC interrupt
; dispatch vector can be moved to be the same vector (in Via2DT)
; that the Mac II uses. Incorporated the change to PowerOff that
; was made for the SE/30, so that if the power doesn't go off, it
; will return from the trap. Greatly improved the performance of
; VIA interrupt handlers, removed the shifting/search loop, and
; replaced it with a fast table lookup.
; <1.6> 2/17/89 rwh don't pass VBase2 to SoundInt so it builds. SoundInt is an rts
; for now anyway...
; <1.5> 2/16/89 rwh added power off for OSS based machines.
; <1.4> 2/7/89 GGD Fixed DebugUtil to work on F19 too. Added MSH's Esprit changes
; (see him for info).
; <1.3> 12/14/88 MSH Removed idle code from level 1 dispatch, also fixed up speed
; code saving.
; <1.2> 12/13/88 rwh fix IopBypassInterrupt handling - better solution need IOPMgr
; work as well.
; <1.1> 11/10/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; <2.2> 11/6/88 GGD Ported to IoMac, added DebugUtil trap code for debugger support.
; <2.1> 11/1/88 MSH Rearranged the test order for doing deferred tasks.
; <2.0> 10/24/88 djw Added hasRBV conditional in SlotInt.
; <1.9> 10/5/88 CSL Added support for RBV.
; <1.8> 9/24/88 rwh add ExitInt label to level 5 dispatcher so MvMac build works.
; <•1.7> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles
; <1.6> 9/16/88 rwh Roll-in onMvMac changes, including ggd's improved deferred task
; dispatcher.
; <1.5> 9/9/88 MSH New version of speed saving and idle entry. Idle now is checked
; <1.4> 8/5/88 MSH Protecting savespeedo from being trashed by level 2 interrupt
; during level 1 interrupt servicing.
; <1.3> 7/8/88 MSH Added test for SCC enabled before reading interrupt register.
; <1.2> 4/21/88 djw Fixed hcMac bug in level 2 int hndlr for differentiating SCC and
; sound interrupts. Added restoring speedometer low mem.
; <1.1> 2/15/88 BBM modified for mpw 3.0 equates
; <1.0> 2/10/88 BBM Adding file for the first time into EASE…
; <Cxxx> 1/22/88 rwh Fixed Lvl5Int - needed to pop return addr off stack for bypass
; ints. <1.6>
; <Cggd> 12/18/87 ggd Changed polarity of slot interrupt bits for MvMac. <1.6>
; <C985> 12/17/87 MSH Added deferred task stuff for Laguna and clock speed support
; too.
; <C926> 11/3/87 rwh Roll in PB231: Fix deferred task dispatcher to dequeue task
; BEFORE calling it
; <C914> 10/29/87 rwh Port to Modern Victorian
; <C894> 9/30/87 MSH Port to HcMac (Laguna)
; <PB091> 4/20/87 RDC Rolled in patch from ROM78Fix for poweroff routine
; <C811> 2/13/87 RDC Add hook in deferred task routine for posterity
; <C803> 2/12/87 RDC Fix bug that allows deferred tasks to override VBL tasks
; <C705> 1/27/87 RDC Add fix to protect level 1 interrupts more globally from 32-bit
; mode. Deleted check in VBL handlers.
; <C694> 1/26/87 RDC Added various bug fixes
; <C686> 1/25/87 RDC Code review cleanup
; <C582> 1/2/87 RDC Remove MMU mode swap when dispatching to slot interrupt
; routines, add misc cleanup
; <C556> 12/19/86 FJL Changed NumSlots to sNumSlots for GWN.
; <C334> 12/9/86 JSP Added testing and use of MMU mode swapping to levels 1,2, and 4.
; <C409> 12/7/86 RDC Added deferred task support, cleaned up comments
; <C400> 11/11/86 RDC Another bug fix in interrupt handler for slot priority
; <C390> 11/10/86 RDC Fixed bug in interrupt handler for slot priority
; <A327> 11/2/86 RDC Finally added the copyright notice!
; <A261> 10/24/86 CSL Took out one autopoll per VBL for mouse data update.
; <C243> 10/18/86 RDC Added fix to SlotVBLInt to leave interrupts disabled for now
; <C166> 10/13/86 RDC Added use of slot priority table in Numac slot interrupt handler
; Changed slot int handling to use low mem ptr to int queue table
; <C147> 10/13/86 RDC Added changes for separation of VBL handling for NuMac since VBL
; tasks can now be assigned to a specific slot. Increased poweroff
; delay to two seconds for disk eject. Removed call to keyboard
; task for new systems.
; <C199> 10/3/86 CSL Set one autopoll per VBL for mouse data update. Fixed in Kbd.a
; and Crsrcore.a. Changed include files
; <C121> 8/20/86 RDC Added change to NuMac slot interrupt handler to fix problem of
; missing slot interrupts
; <C120> 8/19/86 RDC Added reset of NuMac VIA int flag bit for slots in the slot
; interrupt handler so cards don't have to do it.
; <C112> 8/7/86 RDC Added comment changes for new NuMac hardware (VIA2 interrupt
; changes)
; <C101> 8/2/86 RDC Added fix for handling multiple slot interrupts
; <C84> 8/1/86 WRL Skip jCrsrTask in VBL handler if it's NIL.
; <C92> 7/29/86 RDC deleted video interrupt handler - now on video cards
; <C88> 7/28/86 RDC Added changes for handling NuMac slot interrupts.
; <C68> 7/17/86 RDC Increased poweroff delay loop to one sec to allow time for disk
; eject; changed routine name to Poweroff for trap use
; <C51> 6/24/86 RDC Added debounce loop to NuMac poweroff int handler
; <C48> 6/17/86 RDC Fixed bug in NuMac poweroff int handler
; <C42> 6/11/86 RDC Added interrupt handler for NuMac poweroff interrupt
; <C28> 5/30/86 CSL Added changes for Aladdin, and Aladdin Front desk bus support.
; <C9> 5/21/86 RDC Fixed slot interrupt dispatcher to check for interrupts from all
; slots before exiting
; <C1> 4/15/86 RDC Added changes for 020 Reno project (NuMac) - removed call to
; cursor task (called by slot interrupt handler) - Added interrupt
; handler for second VIA and for slots - Added video card
; interrupt handler
; 2/19/86 BBM Made some modifications to work under MPW
; 1/15/86 ELR Removed SCSI interrupt handler, in keeping with the fact that
; SCSI interrupts were removed.
; 9/25/85 LAK Finally fixed outstanding bug in SCC ext/sts dispatch: we 'and'
; the status with RR15 value so we just consider bits which are
; enabled to cause interrupts. Without this fix, an external clock
; can cause us to ignore half of our mouse interrupts (this is
; also seen when connected to AppleTalk on a very busy network).
; 9/6/85 ELR Added code to field SCSI chip interrupts on LVL1 int vector.
; (OnMac)
; 7/24/85 RDC Added spearate include statement for HWequ file (no longer in
; systlqk.sym)
; 7/23/85 RDC Added mouse interrupt routines from CrsrCore Added changes for
; MidMac - removed mouse int routines (handled by Front Desk Bus)
; - added call of keyboard task every VBL int
; 1/29/85 LAK Put RAM patch code in (one sec int support for alarm).
; 1/23/85 LAK Adapted for new equate files.
; 8/19/83 LAK StkLowPt now managed by VBL handler; calls SysError in case of
; stack crashing into heap.
; 8/17/83 LAK Now calls cursor task via a lowmem vector.
; 8/6/83 LAK Increments random number seed when mouse button changes. Saved
; some code by pointing Lvl1RTS and Lvl2RTS at an RTS and Spurious
; at an RTE.
; 6/10/83 LAK Changed level 2 interrupt handler (see comments there).
; 6/10/83 LAK Added delay between SCC write and read (was only 6 pclks + 50ns)
; by loading 'and' mask before reading SCC interrupt vector.
; Changed ext int handler to ignore mouse movements when any other
; external condition has happened.
; 2/16/83 LAK VBL interrupt dispatcher calls keyboard manager thru KybdTask
; vector.
; 11/15/82 LAK no more deferred task manager
; 11/5/82 LAK only high bit of MBState set now (just a little bit nicer)
; 8/26/82 LAK updated for 512-dot machine
; 8/15/82 LAK A0-A1 point to appropriate port; save more registers; put in
; secondary ext/sts dispatch routine
; 8/10/82 LAK brought deferred task handler here from Dispatch
; 6/4/82 LAK changed VBL handler to call keyboard task only every 32
; interrupts.
; 5/2/82 LAK adapted to the SCC hardware; uses SCC interrupt vector to decide
; which service routine to go to
; 4/29/82 LAK adapted to the SCC hardware, included mouse button handler from
; KBD.
; 10/5/81 bmw made it check deferred tasks on exit
; 5/13/81 AJH added Level 1 Interrupt Handler
;
; To Do: There is a potential problem when calling VRemove while the Vertical Retrace
; Manager is executing. This is only a problem for interrupt routines that call
; VRemove, so it can be avoided by placing the restriction that such routines
; may remove a VBL task only by letting its count expire.
;
;-----------------------------------------------------------------------------------------
print push,off
load 'StandardEqu.d'
include 'HardwarePrivateEqu.a'
include 'SysPrivateEqu.a'
include 'UniversalEqu.a'
include 'IOPrimitiveEqu.a'
include 'ShutDown.a'
IF hasPwrControls THEN
include 'PowerPrivEqu.a'
ENDIF
IF hasEgret THEN
include 'EgretEqu.a'
ENDIF
IF hasPSC THEN
include 'PSCEqu.a'
ENDIF
IF hasAMIC THEN
include 'AMICEqu.a'
ENDIF
IF hasGrandCentral THEN
include 'GrandCentralPriv.a'
ENDIF
print pop
print nomdir
machine mc68020
; interrupt setup primitives record
InterruptPrims RECORD {intInitPostProc},INCREMENT
flags DS.W 1 ; miscellaneous flags
count DS.W 1 ; number of entries in the table
intInitPostProc DS.L 1 ; post initialization dynamic setup
intDisableInts DS.L 1 ; disable all interrupt sources
intEnableOneSec DS.L 1 ; enable one second interrupts
intEnableSlots DS.L 1 ; enable slot interrupts
intEnableSound DS.L 1 ; enable sound interrupts
intDisableSound DS.L 1 ; disable sound interrupts
intClearSound DS.L 1 ; clear sound interrupts
intEnableSCSI DS.L 1 ; enable SCSI interrupts
intDisableSCSI DS.L 1 ; disable SCSI interrupts
intClearSCSIInt DS.L 1 ; clear SCSI interrupts
intPowerOffProc DS.L 1 ; custom power off code
intFirstVectTbl DS.L 1 ; first vectors table (end with a zero)
ENDR
; rename a few historical equates for clarity
Via1DT equ Lvl1DT ; dispatch table for VIA1 interrupts
SccDT equ Lvl2DT ; dispatch table for SCC interrupts
; define equates for common VIA dispatch table entries
jOneSecInt equ Via1DT+4*ifCA2 ; valid on all machines
jVBLInt equ Via1DT+4*ifCA1 ; valid on all machines
jKbdAdbInt equ Via1DT+4*ifSR ; not valid when IopADB or PwrMgrADB
jSlotInt equ Via2DT+4*ifCA1 ; valid when hasSlotMgr
jASCInt equ Via2DT+4*ifCB1 ; valid when hasASC
jSCSIIrqInt equ Via2DT+4*ifCB2 ; valid when has something VIA2-like
IntHnd proc export
import OneSecInt, VBLInt, IOPInterrupt
WITH ProductInfo, InterruptPrims
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: DisableIntSources
;
; Inputs: none
;
; Outputs: none
;
; Trashes: A0
;
; Function: disables the external interrupt sources to prevent processor interrupts from occurring
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export DisableIntSources
DisableIntSources
MOVEA.L UnivInfoPtr,A0 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A0),A0 ; then to the interrupt handlers primitives table,
ADDA.L intDisableInts(A0),A0 ; and finally to the routine to disable interrupts
JMP (A0) ; call it
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: Enable60HzInts
;
; Inputs: none
;
; Outputs: none
;
; Trashes: D0/A0-A1
;
; Function: enables the 60Hz interrupt source, so that when the processor interrupt
; mask is low enough, the interrupts will be generated
;
; 60Hz interrupts are generated either by VIA hardware or by a Time Manager
; task. The proper method is indicated in ProductInfo.
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export Enable60HzInts
Enable60HzInts
TestFor SoftVBL
beq.b @VIAVBL
@TMVBL
import PseudoVBLInt
moveq.l #tmXQSize, d0 ; allocate a block in the system heap
_NewPtr ,SYS,CLEAR ; to hold the Time Manager task structure
lea PseudoVBLInt, a1
move.l a1, tmAddr(a0)
move.l #'eada', (a0) ; identify queue type to VM
_InsXTime
move.l #-16626, d0
move.l jPrimeTime, a1
jmp (a1)
@VIAVBL
movea.l VIA,a0 ; it is a VIA1 interrupt source
eieioSTP
move.b #(1<<ifIRQ)|(1<<ifCA1),vIER(a0) ; enable the CA1 interrupt
eieioSTP
rts
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: EnableOneSecInts
;
; Inputs: none
;
; Outputs: none
;
; Trashes: A0
;
; Function: enables the one second interrupt source, so that when the processor
; interrupt mask is low enough, the interrupts will be generated
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export EnableOneSecInts
EnableOneSecInts
MOVEA.L UnivInfoPtr,A0 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A0),A0 ; then to the interrupt handlers primitives table,
ADDA.L intEnableOneSec(A0),A0 ; and finally to the routine to enable one second interrupts
JMP (A0) ; call it
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: EnableSlotInts
;
; Inputs: none
;
; Outputs: none
;
; Trashes: A0
;
; Function: enables the NuBus slot interrupt source, so that when the processor
; interrupt mask is low enough, the interrupts will be generated
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export EnableSlotInts
EnableSlotInts
MOVEA.L UnivInfoPtr,A0 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A0),A0 ; then to the interrupt handlers primitives table,
ADDA.L intEnableSlots(A0),A0 ; and finally to the routine to enable slot interrupts
JMP (A0) ; call it
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: EnableSoundInts
;
; Inputs: none
;
; Outputs: none
;
; Trashes: A0
;
; Function: enables the sound interrupt source, so that when the processor
; interrupt mask is low enough, the interrupts will be generated
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export EnableSoundInts
EnableSoundInts
MOVEA.L UnivInfoPtr,A0 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A0),A0 ; then to the interrupt handlers primitives table,
ADDA.L intEnableSound(A0),A0 ; and finally to the routine to enable sound interrupts
JMP (A0) ; call it
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: DisableSoundInts
;
; Inputs: none
;
; Outputs: none
;
; Trashes: A0
;
; Function: disables the sound interrupt source, so that processor
; interrupts will not be generated
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export DisableSoundInts
DisableSoundInts
MOVEA.L UnivInfoPtr,A0 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A0),A0 ; then to the interrupt handlers primitives table,
ADDA.L intDisableSound(A0),A0 ; and finally to the routine to disable sound interrupts
JMP (A0) ; call it
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: ClearSoundInt
;
; Inputs: none
;
; Outputs: none
;
; Trashes: A0
;
; Function: Disables the sound interrupt source, so that processor interrupts will
; not be acknowledged. Note that this only clears the interrupt at the
; secondary source (VIA/RBV/...) and it is expected that the caller will
; clear it at the sound chip.
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export ClearSoundInt
ClearSoundInt
MOVEA.L UnivInfoPtr,A0 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A0),A0 ; then to the interrupt handlers primitives table,
ADDA.L intClearSound(A0),A0 ; and finally to the routine to clear sound interrupts
JMP (A0) ; call it
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: EnableSCSIInts
;
; Inputs: none
;
; Outputs: none
;
; Trashes: A0
;
; Function: enables the SCSI interrupt source, so that when the processor
; interrupt mask is low enough, the interrupts will be generated
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export EnableSCSIInts
EnableSCSIInts
MOVEA.L UnivInfoPtr,A0 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A0),A0 ; then to the interrupt handlers primitives table,
ADDA.L intEnableSCSI(A0),A0 ; and finally to the routine to enable SCSI interrupts
JMP (A0) ; call it
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: DisableSCSIInts
;
; Inputs: none
;
; Outputs: none
;
; Trashes: A0
;
; Function: disables the SCSI interrupt source, so that processor
; interrupts will not be generated
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export DisableSCSIInts
DisableSCSIInts
MOVEA.L UnivInfoPtr,A0 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A0),A0 ; then to the interrupt handlers primitives table,
ADDA.L intDisableSCSI(A0),A0 ; and finally to the routine to disable SCSI interrupts
JMP (A0) ; call it
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: ClearSCSIInt
;
; Inputs: none
;
; Outputs: none
;
; Trashes: A0
;
; Function: Disables the SCSI interrupt source, so that processor interrupts will
; not be acknowledged. Note that this only clears the interrupt at the
; secondary source (VIA/RBV/...) and it is expected that the caller will
; clear it at the SCSI chip.
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export ClearSCSIInt
ClearSCSIInt
MOVEA.L UnivInfoPtr,A0 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A0),A0 ; then to the interrupt handlers primitives table,
ADDA.L intClearSCSIInt(A0),A0 ; and finally to the routine to clear SCSI interrupts
JMP (A0) ; call it
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: PowerOff (trap $A05B)
;
; Inputs: none
;
; Outputs: D0 - result code (always zero)
;
; Trashes: A0
;
; Function: This routine tries to turn off the power to the computer (if it's possible
; to do that). If power can't be turned off by software, it'll just return
; and the ShutDown software can put up a dialog instead.
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export PowerOff
PowerOff
MOVEA.L UnivInfoPtr,A0 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A0),A0 ; then to the interrupt handlers primitives table,
ADDA.L intPowerOffProc(A0),A0 ; and finally to the routine to power off the computer
JSR (A0) ; call it
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: DebugUtil (trap $A08D)
;
; Inputs: D0 - selector
; 0 - return highest function number supported
; 1 - entering debugger (for debugger to inform the system)
; 2 - exiting debugger (for debugger to inform the system)
; 3 - run keyboard polling code without interrupts
;
; Outputs: D0 - result (dependent on selector)
;
; Trashes: none (A0-A2/D1-D2 are saved by OS trap dispatcher)
;
; Function: performs hardware dependent functions for the debugger, so that each time
; a new hardware design comes out we don't need a new debugger
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export DebugUtil
DebugUtil
lea @table,a0 ; point to the decoding table
cmp.l (a0)+,d0 ; range check the selector
bhi.s @tooBig ; if out of range
add.w d0,d0 ; table entries are 2 bytes each
adda.w (a0,d0.w),a0 ; point to the procedure
jmp (a0) ; execute the routine
@tooBig moveq.l #paramErr,d0 ; param error if out of range
rts ; all done
ALIGN 4
@table dc.l (@last-@first)/2-1 ; highest function number supported
@first
dc.w @getMax-@first ; 0 - return highest function number supported
dc.w DebugEnter-@first ; 1 - entering debugger
dc.w DebugExit-@first ; 2 - exiting debugger
dc.w DebugPoll-@first ; 3 - run keyboard polling code without interrupts
@last
@getMax move.l @table,d0 ; get the max
rts ; return it in D0
DebugEnter MOVEQ #4*adbDebugEnter,D0 ; table index for entry routine
BRA.S DebugUtilDispatch
DebugExit MOVEQ #4*adbDebugExit,D0 ; table index for exit routine
BRA.S DebugUtilDispatch
DebugPoll MOVEQ #4*adbDebugPoll,D0 ; table index for polling routine
* BRA.S DebugUtilDispatch
DebugUtilDispatch
MOVEM.L D1-D3/A0-A3,-(SP)
MOVEA.L UnivInfoPtr,A0 ; point to the ProductInfo table
ADDA.L ProductInfo.ADBDebugUtilPtr(A0),A0 ; and get the address of its ADB table
MOVE.L 0(A0,D0),D0 ; get the offset to the specified routine
BEQ.S @NoProc ; -> this function is not supported
ADDA.L D0,A0 ; calculate the routine's address
JSR (A0) ; and call it
@NoProc MOVEM.L (SP)+,D1-D3/A0-A3
MOVEQ #noErr,D0 ; always return with success
RTS
;———————————————————————————————————————————————————————————————————————————————————————
; Interrupt Primitive Routines
;
; Function: Implement hardware dependent interrupt enable functions underlying
; the abstract entry points above.
;———————————————————————————————————————————————————————————————————————————————————————
IF hasMac2VIA2 | hasRBV | hasEclipseVIA2 THEN
; - - - - - VIA/RBV primitives - - - - -
VIADisableIntSources
movea.l VIA,a0 ; disable all interrupts in VIA1
eieioSTP
move.b #$7F,vIER(a0)
movea.l VIA2RBV,a0
eieioSTP
move.b #$7F,Rv2IER(a0) ; and in VIA2
eieioSTP
rts
VIAEnableOneSecInts ; enable one second interrupts by setting CA2
movea.l VIA,a0 ; in the VIA1 enables register
eieioSTP
move.b #(1<<ifIRQ)|(1<<ifCA2),vIER(a0)
eieioSTP
rts
VIAEnableSlotInts ; enable slot interrupts by setting CA1
movea.l VIA2RBV,a0 ; in the VIA2 enables register
eieioSTP
move.b #(1<<ifIRQ)|(1<<ifCA1),Rv2IER(a0)
eieioSTP
rts
VIAEnableSoundInts ; enable sound interrupts by setting CB1
movea.l VIA2RBV,a0 ; in the VIA2 enables register
eieioSTP
move.b #(1<<ifIRQ)|(1<<ifCB1),Rv2IER(a0)
eieioSTP
rts
VIADisableSoundInts ; disable sound interrupts by clearing CB1
movea.l VIA2RBV,a0 ; in the VIA2 enables register
eieioSTP
move.b #(0<<ifIRQ)|(1<<ifCB1),Rv2IER(a0)
eieioSTP
rts
VIAClearSoundInts ; clear a sound interrupt by setting CB1
movea.l VIA2RBV,a0 ; in the VIA2 flags register
eieioSTP
move.b #(1<<ifIRQ)|(1<<ifCB1),Rv2IFR(a0)
eieioSTP
rts
VIAEnableSCSIInts ; enable SCSI IRQ by setting CB2
movea.l VIA2RBV,a0 ; in the VIA2 enables register
eieioSTP
move.b #(1<<ifIRQ)|(1<<ifCB2),Rv2IER(a0)
eieioSTP
rts
VIADisableSCSIInts ; disable SCSI IRQ by clearing CB2
movea.l VIA2RBV,a0 ; in the VIA2 enables register
eieioSTP
move.b #(0<<ifIRQ)|(1<<ifCB2),Rv2IER(a0)
eieioSTP
rts
VIAClearSCSIInts ; clear SCSI IRQ by setting CB2
movea.l VIA2RBV,a0 ; in the VIA2 flags register
eieioSTP
move.b #(1<<ifIRQ)|(1<<ifCB2),Rv2IFR(a0)
eieioSTP
rts
VIAPowerOff movea.l VIA2RBV,A0
moveq.l #v2PowerOff,d0 ; get power off bit number
eieioSTP
bset.b d0,vDirB++RvDataB(a0) ; make the VIA/RBV bit an output
eieioSTP
bclr.b d0,vBufB++RvDataB(A0) ; and clear it to turn off the power
eieioSTP
rts
ENDIF
IF hasPwrControls THEN
; - - - - - Power Manager primitives - - - - -
WITH pmCommandRec
IMPORT StartBoot
; power off the computer using the PMGR
PMgrPowerOff
IF isUniversal THEN
TestFor hwCbPwrMgr
beq.s PmgrOffDone
ENDIF
CLR.L -(SP) ; pmRBuffer = nil
CLR.L -(SP) ; pmRBuffer = nil
CLR.W -(SP) ; pmLength = 0
MOVE.W #PmgrADBoff,-(SP) ; pmCommand = turn ADB autopoll off
MOVE.L SP,A0 ; point to the parameter block
_PmgrOp
LEA pmRBuffer+4(SP),SP ; clean up the stack
_HideCursor
CLR.L WarmStart ; be sure to do startup testing
; If we have the new PMGR then this command will work. If not then the call will
; fail and we will do it the old fashioned way.
PEA 'MATT' ; shutdown signature <H4>
MOVE.L SP,-(SP) ; pmRBuffer (not used) <H4>
MOVE.L (SP),-(SP) ; pmSBuffer (the sleep signature) <H4>
MOVE.W #4,-(SP) ; pmLength = 4 <H4>
MOVE.W #PmgrPWRoff,-(SP) ; pmCommand = power off <H4>
MOVE.L SP,A0 ; point to the parameter block <H4>
_PmgrOp ; power off using the PMGR <H4>
LEA pmRBuffer+4+4(SP),SP; clean up the stack <H4>
BNE.S @callSleep ; -> the call failed, so we have an old PMGR <H4>
BRA.S * ; Let the cyanide take affect
@callsleep MOVE.W #SleepNow,D0 ; Set it to sleep
_Sleep
BigJSR StartBoot,A0 ; Reboot the guy.
PmgrOffDone
RTS
ENDWITH ; {pmCommandRec}
ENDIF ; {hasPwrControls}
IF hasIopSwim THEN
; - - - - - SWIM IOP primitives - - - - -
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: EnableSwimIOPInts
;
; Inputs: none
;
; Outputs: none
;
; Trashes: A0
;
; Function: enables the SWIM IOP interrupt source, so that when the processor
; interrupt mask is low enough, the interrupts will be generated
;———————————————————————————————————————————————————————————————————————————————————————
export EnableSwimIOPInts
EnableSwimIOPInts
IF hasOSS THEN
TestFor OSSExists ; see if we really have an OSS
beq.s @notOSS ; if not, use the VIA2/RBV
movea.l OSS,a0 ; get OSS base
eieioSTP
move.b #MskIOP1,OSSMskPSwm(a0) ; enable the SWIM IOP interrupt mask
eieioSTP
rts
@notOss
ENDIF ; {hasOSS}
movea.l VIA2RBV,a0 ; Get base address of VIA2/RBV
eieioSTP
move.b #(1<<ifIRQ)|(1<<ifCA2),Rv2IER(a0) ; SWIM IOP interrupt is CA2
eieioSTP
rts
;_______________________________________________________________________
;
; Secondary Dispatch routines for IOP 1 interrupts
;
; On Entry: A1.L = VIA2 base address (if hasMac2Via2 only)
; D0-D3/A0-A3 have been saved
;
;_______________________________________________________________________
align alignment ; align on cache line boundary
SwimIopIntVIA
eieioSTP
move.b #1<<ifCA2,VIFR(A1) ; reset VIA2 int. flag
eieioSTP
SwimIopInt moveq.l #1,d0 ; Swim IOP is IOP number 1
eieioSTP
jmp IOPInterrupt ; handle the interrupt and return
eieioSTP
ENDIF ; {hasIopSwim}
IF hasEgret THEN
; - - - - - Egret primitives - - - - -
WITH EgretPB
; This routine will enable the one second IRQ in Egret. The Mode will be 3 which forces
; tick packets first and if Egret cannot send the packet then it will send a Read Real
; Time Clock command. This command returns the full 32 bit time setting back to the system.
EgretEnableOneSecInts
lea -EgretPBSize(sp),sp ; build a record on the stack
move.l sp,a0 ; point to the start of the record
move.b #pseudopkt,pbCmdType(a0) ; we want a pseudo request
move.b #wr1secmode,pbCmd(a0) ; Start 1 sec irq Mode 3
move.b #3,pbParam(a0)
clr.l pbCompletion(a0) ; nil completion vector pointer
_EgretDispatch ; issue the call Egret Manager
lea EgretPBSize(sp),sp ; Discard the record
rts
; This routine will issue a Power off command to Egret. If the call succeeds, the power
; supply will be turned off and the system will sleep. If the poweroff command cannot turn
; off the supply then the call will return and the system will display a restart dialog.
EXPORT EgretPowerOff
EgretPowerOff
lea -EgretPBSize(sp),sp ; build a record on the stack
move.l sp,a0 ; point to the start of the record
move.b #pseudopkt,pbCmdType(a0) ; we want a pseudo request
move.b #pwrdown,pbCmd(a0) ; PowerDown Command
move.b #0,pbParam(a0) ; A zero stops autopoll
clr.l pbCompletion(a0) ; nil completion vector pointer
_EgretDispatch ; issue the call Egret Manager
lea EgretPBSize(sp),sp ; clean up the stack
bra WaitAWhile ; if it returns then Power Off failed
; Wait an additional 1.5 seconds for for power to turn off.
; If it doesn't we just return from the _PowerOff trap.
WaitAWhile
move.l #(-1500)<<16,d0 ; outer loop count 500*1ms
@outer move.w TimeDBRA,d0 ; inner loop count 1ms
@inner dbra d0,@inner ; wait 1ms
addq.l #1,d0 ; increment outer loop counter
bne.s @outer ; wait 500*1ms
rts ; the long wait is over
ENDWITH ; {EgretPB}
ENDIF ; {hasEgret}
IF hasPSC THEN
; - - - - - PSC primitives - - - - -
PSCInitPostProc
TestFor MUNIExists ; Install MUNI Interrupt handler in VIA2 Dipatch Table
beq.s @NoMuni ; No Muni
Move.l #1, MUNIBase+MUNI_IntCntrl ; disable MUNI interrupts (no handler)
@NoMuni
WITH ExpandMemRec, PSC_INT_TBL
move.l #PSC_INT_TBL_SZ,D0 ; 8 bytes needed per table entry
_NewPtr ,SYS,CLEAR ; allocate it and zero out the memory
move.l a0,([ExpandMem],emDMADispatchGlobals) ; and save it
beq.b @noPSC ; abort further installation if Ptr is nil
; For compatibility with third-party serial driver replacements like MIDI, MacRecorder, etc.
; The old SCC interrupt handler code is installed into the PSC interrupt table and SCC
; interrupts are enabled through the PSC. This should make the PSC implementation look just
; like the traditional implementation.
;
lea SccDecode,a1 ; default SCC interrupt handler
move.l a1,L4SCCAhndlr(a0) ; services port A
move.l a1,L4SCCBhndlr(a0) ; services port B
movea.l UnivInfoPtr,a0
adda.l ProductInfo.DecoderInfoPtr(a0),a0
movea.l DecoderInfo.PSCAddr(a0),a0
move.b #1 << L4B7 | 1 << L4SCCB | 1 << L4SCCA, L4IER(a0)
@noPSC
ENDWITH ; {ExpandMemRec, PSC_INT_TBL}
RTS
PSCDisableIntSources
movea.l VIA,a0 ; VIA1 base address
move.b #$7F,vIER(a0) ; disable all interrupts
movea.l VIA2,a0 ; VIA2 base address
Move.b #$6F,vIER(a0) ; disable all interrupts
rts ; continue with our program
PSCEnableSlotInts
movea.l VIA2,a0 ; VIA2 base address
move.b #(1<<ifIRQ)|(1<<ifCA1),\ ; any slot interrupt is CA1
vIER(a0) ; enable the CA1 interrupt
rts
PSCEnableSCSIInts
movea.l VIA2,a0 ; VIA2 base address
Move.b #(1<<ifIRQ)|(1<<ifCB2),\ ; SCSI IRQ interrupt is CB2
vIER(a0) ; enable the SCSI interrupt
rts ; were are out of here...
PSCDisableSCSIInts
movea.l VIA2,a0 ; VIA2 base address
Move.b #(0<<ifIRQ)|(1<<ifCB2),\ ; SCSI IRQ interrupt is CB2
vIER(a0) ; enable the SCSI interrupt
rts ; were are out of here...
ENDIF ; {hasPSC}
IF hasAMIC THEN
; - - - - - AMIC primitives - - - - -
;________________________________________________________________________________________
;
; Routine: AMICInitPostProc
;
; Inputs: none
; Outputs: none
; Trashes: D0, A0
;
; Function: Sets up DMA base addresses and installs IRQ handler the channel(s). Sets the
; Reset bit for each channel; configures AMIC for the I/O bus speed of the machine.
;
; Note: Requires that ExpandMem and MemoryDispatch have been initalized.
;________________________________________________________________________________________
WITH MemDispGlobals, ExpandMemRec, DMADispGlobals
DMALogBufferAddrPDM EQU $61000000 ; Hard code this for now (This is the logical buffer address)
AMICInitPostProc
MOVEA.L UnivInfoPtr,A2
ADDA.L ProductInfo.DecoderInfoPtr(A2),A2 ; Get the addr of the universal base addresses
MOVEA.L DecoderInfo.AMICAddr(A2),A2 ; Get AMIC's DMA base address
MOVE.L ([LockMemCt],mdLog2PageSize),D1 ; Get the current log2 MMU page size
MOVE.L #DMALogBufferAddrPDM,D0 ; Get the hard coded logcal address of the DMA buffer
; that the nanokernel has allocated for us
LSR.L D1,D0 ; Turn the Log addr into a page number
MOVE.L D0,A0 ; Put the page in A0
_nkMMUGetPhysicalPage ; Get the physical page number in D0
LSL.L D1,D0 ; Turn the page into an address
; Issue a soft reset to all the DMA channels. Too bad a restart doesn't pull the RESET line.
MOVEQ #0,D1 ; Clear D1
LEA @AMICcontrolRegs,A0 ; Point to the table of offsets for the channel control regs
@ResetLoop MOVE.W (A0)+,D1 ; Get an offset
BEQ.S @ResetSound ; -> End of table reached.
BSET.B #0,(A2,D1) ; Set the channel Reset bit
BRA.S @ResetLoop ; -> Do it once for each channel
@ResetSound BCLR.B #0,$50F14010 ; Disable Sound Output <MC5>
BCLR.B #7,$50F14011 ; Disable Sound Input <MC5>
; Get the I/O bus speed and configure AMIC accordingly
@BusSpeed MOVE.L ([ProcessorInfoPtr],\
ProcessorInfo.BusClockRateHz),D1 ; Get the I/O bus clock rate
LEA @CommonClockRates,A0 ; Point to the list of clock rates
MOVEQ #3,D2 ; Start with the least delays (inverse)
@Lupe CMP.L (A0)+,D1 ; Is the bus clock rate less than the entry?
BLS.S @GotIt ; -> Yes, go with the current delay factor
DBRA D2,@Lupe ; -> Decrement the delay factor an loop again
@GotIt BFINS D2,AMICSCSIcntrl(A2){4,2} ; Put bits 0 & 1 from D2 into bits 2 & 3 in AMIC
; LSL.B #2,D2 ; Shift bits 0 & 1 over to 2 & 3.
; MOVEQ #$0C,D1 ; Make a mask for bits 2 & 3
; AND.B AMICSCSIcntrl(A2),D1 ; Mask out the bus speed bits
; OR.B D2,D1
; MOVE.B D1,AMICSCSIcntrl(A2) ; Get the SCSI DMA control byte
; Set the AMIC DMA buffer base address (the physical address in D0)
SWAP D0 ; Put the upper 16 significant bits into the lower 16
MOVE.B D0,AMICSCSIDMABase+1(A2) ; Write the Base Address 8 bits at a time
LSR.W #8,D0 ; Get the MSB
MOVE.B D0,AMICSCSIDMABase(A2) ; Write it (Amic ignores the lower 18 bits of the base)
; Create a dispatch table in the system heap for the system interrupt dispatcher.
MOVE.L #ddSize,D0 ; Size of the Dispatch table
_NewPtr ,Sys,Clear ; Get the RAM in the system heap (die if we don't get it)
move.l A0,([ExpandMem],emDMADispatchGlobals) ; Save our global ptr in ExpandMem
beq.b @Done ; ensure that we don't munch on vectors
MOVE.L A2,ddDMAbase(A0) ; Save AMIC's base address in the Table
; Initialize the table to point to the Uninitalized/Spurious IRQ vector.
; Slam the SCC handler address into the designated entries in the table.
MOVE.L BadIntVector, D1 ; Get the Addr of the spurious IRQ handler
MOVEQ #ddVectCount-1, D0 ; Get the number of vectors (zero-based)
@InitVector MOVE.L D1, ddVector0(A0,D0.L*8) ; Initialize each vector to Spurious
DBRA D0, @InitVector ; -> Loop till they're all done
LEA SccDecode, A2 ; Point to the SCC irq handler
MOVE.L A2, SCCLvl4Avector(A0) ; Stuff the address into the Table
MOVE.L A2, SCCLvl4Bvector(A0) ; Me too (for port B)
@Done RTS
@AMICcontrolRegs ; Table of offsets to each channel's control reg
DC.W AMICSCSICntrl
DC.W AMICEnetTxCntrl
DC.W AMICEnetRxCntrl
DC.W AMICFloppyCntrl
DC.W AMICSCCTxACntrl
DC.W AMICSCCRxACntrl
DC.W AMICSCCTxBCntrl
DC.W AMICSCCRxBCntrl
DC.W 0
@CommonClockRates ; PDM I/O bus clock rate mapping table
DC.L 25000000 ; 3: 33.001 MHz
DC.L 40000000 ; 2: 40.001 MHz
DC.L 40000000 ; 1: 50.001 MHz <SM44> pdw
DC.L 100000000 ; 0: 100.001 MHz
DC.L -1 ; end of table
ENDWITH ; {MemDispGlobals, ExpandMemRec, DMADispGlobals}
AMICDisableIntSources
movea.l VIA,a0 ; disable all interrupts in VIA1
move.b #$7F,vIER(a0)
movea.l VIA2RBV,a0
move.b #$7F,Rv2IER(a0) ; and in VIA2
move.l UnivInfoPtr,a0 ; get ptr to ProductInfo
add.l ProductInfo.DecoderInfoPtr(a0),a0 ; point to the base address table
move.l DecoderInfo.AMICAddr(a0),a0 ; get ptr to AMIC
move.b #(1<<DMARST),AMIC_DMA_RECV_CNTL(a0) ; reset DMA channel, disable ints
move.b #(1<<DMARST),AMIC_DMA_XMIT_CNTL(a0) ; reset DMA channel, disable ints
nop
TestFor MACEExists ; do we have MACE hardware? <GMR>
beq.s @exit ; no, skip
move.l UnivInfoPtr,a0 ; get ptr to ProductInfo
add.l ProductInfo.DecoderInfoPtr(a0),a0 ; point to the base address table
move.l DecoderInfo.MACEAddr(a0),a0 ; Save the MACE base address
; st.b MACE_INT_MSK(a0) ; Disable MACE ints. (I'll fix the equates later)
st.b $90(a0) ; Disable MACE ints.
nop
@exit rts
ENDIF ; {hasAMIC}
IF hasGrandCentral THEN
; - - - - - Grand Central primitives - - - - -
WITH ExpandMemRec, GCInterruptDispatchTable
GCInitPostProc
; build a table for the Grand Central interrupt dispatcher
move.l #GCInterruptDispatchTable.size,d0
_NewPtr ,sys,clear ; allocate memory for a dispatch table
move.l a0,([ExpandMem],emDMADispatchGlobals) ; save a reference to the table
beq @EndPostProc ; abort installation if no memory
; save the Grand Central base address in the interrupt dispatch table
movea.l UnivInfoPtr,a1
adda.l ProductInfo.DecoderInfoPtr(a1),a1
movea.l DecoderInfo.GrandCentralAddr(a1),a1
move.l a1,gcBaseAddr(a0)
; initialize dispatch vectors to the value of the spurious interrupt vector
move.l BadIntVector,d1
moveq #31,d0
@InitVector move.l d1,gcVector(a0,d0.l*8)
dbra d0,@InitVector
; enable the default VIA interrupt handler
_GCEnableInterruptSource gcifDevVia
; install the default SCC interrupt handlers
lea SccDecode,a0 ; default SCC interrupt handler
lea 0,a1 ; no reference constant
moveq #gcifDevSccA,d0
_GCRegisterHandler ; now serving port A
moveq #gcifDevSccB,d0
_GCRegisterHandler ; now serving port B
_GCEnableInterruptSource gcifDevSccA
_GCEnableInterruptSource gcifDevSccB
_GCEnableInterruptSource gcifExtNMI ; enable NMI <SM62>
@EndPostProc
rts
ENDWITH ; {ExpandMemRec, GCInterruptDispatchTable}
GCDisableIntSources
bsr.b GetGrandCentralBase
; clear all interrupt mask bits without changing the interrupt mode bit
andi.l #1 << gcifIntMode,gcInterruptMask(a0)
rts
GCEnableSoundInts
bsr.b GetGrandCentralBase
; set the audio interface interrupt enable bit
ori.l #1 << gcifDevAudio,gcInterruptMask(a0)
rts
GCDisableSoundInts
bsr.b GetGrandCentralBase
; clear the audio interface interrupt enable bit
andi.l #~(1 << gcifDevAudio),gcInterruptMask(a0)
rts
GCEnableSCSIInts
bsr.b GetGrandCentralBase
; set the SCSI interface interrupt enable bits
ori.l #1 << gcifDevSCSI0 | 1 << gcifDevSCSI1,gcInterruptMask(a0)
rts
GCDisableSCSIInts
bsr.b GetGrandCentralBase
; clear the SCSI interface interrupt enable bits
andi.l #~(1 << gcifDevSCSI0 | 1 << gcifDevSCSI1),gcInterruptMask(a0)
rts
GetGrandCentralBase
movea.l UnivInfoPtr,a0 ; get a pointer to ProductInfo
adda.l ProductInfo.DecoderInfoPtr(a0),a0 ; point to the base addresses table
movea.l DecoderInfo.GrandCentralAddr(a0),a0 ; get the Grand Central base address
rts
ENDIF ; {hasGrandCentral}
;_______________________________________________________________________
;
; Auto-Vector Interrupts
;
; The autovector routines save intRegs, (typically) perform their second
; level dispatch then jump to FinishInt to service Deferred Tasks and RTE.
; This jump to FinishInt may actually be an explicit BRA or it may be
; done by the autovector routine pushing (PEA) FinishInt then jumping to
; a second-level routine which will RTS into FinishInt. This is better than
; a JSR into the second-level routine followed by a BRA to FinishInt because
; the cache line containing the BRA may have been flushed during the second-
; level routine and when the RTS back to that BRA happens it will take a miss,
; causing a bus cycle. This is avoided by the PEA/JMP.
;
;
; The auto-vectors are assigned as below (according to interrupt priority level):
;
; Level 1: VIA1 interrupts, dispatched through Via1Int using Via1DT
;
; Level 2: VIA2/RBV interrupts, dispatched through Via2Int using Via2DT
;
; Level 3: Ethernet interrupts on some systems
;
; Level 4: SCC interrupts, dispatched through SccDecode using SccDT
; SCC IOP interrupts, dispatched through SccIopInt
;
; Level 5: DSP interrupts
;
; Level 6: unused
;
; Level 7: this interrupt is typically generated only by the debugger switch
;
;
; Routine: FinishInt - Service Deferred Tasks and RTE
;
; Inputs: The stack holds saved 'IntRegs' with an interrupt stack frame above.
; This routine is arrived at by a direct branch from the autovector routines.
;
; Outputs: none
; This routine exits by restoring the saved 'IntRegs' and performing RTE.
;
; Destroys: none
;
; Function: When the interrupt processing has been completed and this routine
; is branched to, it calls any queued deferred tasks (if returning
; to level zero), restores the saved registers, and returns
; from interrupt processing by an RTE instruction.
;
; USED TO:
; Provides a centralized handler for calling a secondary dispatcher.
;
; Creates a consistent environment for all secondary interrupt dispatchers,
; to allow them to easily decode the interrupt source and pass then on to
; other handlers. Registers A0-A3/D0-D3 are always preserved by the caller.
;
; The secondary interrupt dispatcher is called by a JSR and may either return
; with an RTS, or chain to another dispatcher.
;
; If the CPU has a PSC/DSP architecture, this routine calls the DSP Level 2
; handler, if one is present and if RTE will return to an interrupt mask < 2.
; For Sound compatibility with older systems, the DSP Level 5 handler installs
; a "deferred" Level 2 handler/parameter in the PSC Interrupt Table.
;
;_______________________________________________________________________
align alignment ; align on cache line boundary
FinishInt
IF hasPSC THEN
; For systems supporting PSC/DSP only: run the special DSP Level 2 deferred tasks
; for backward compatibility with the VIA2-based sound architecture.
WITH ExpandMemRec, PSC_INT_TBL
TestFor PSCExists
beq.s @noPSCHere
moveq #$06,d0 ; mask for int level in saved SR ($0600)
and.b IntRegsSize(sp),d0 ; are we going to RTE to level 0 or 1?
bne.s @NoDTasks ; no, then certainly no deferred tasks to run
move sr,-(sp) ; save interrupt mask
ori #$0700,sr ; mask all ints
@chkagain move.l ExpandMem,a0
move.l emDMADispatchGlobals(a0),a0 ; get PSC interrupt table ptr
move.l DSPL2hndlr(a0),d0 ; DSP Level 2 hndlr need running?
beq.s @donelp ; no, leave
move.l DSPL2parm(a0),a1 ; pass DSP L2's parm
clr.l DSPL2hndlr(a0) ; remove DSP L2 hndlr from table
movea.l d0,a0
andi #$FAFF,sr ; set interrupt mask to 2
jsr (a0) ; call DSP L2 hndlr
ori #$0700,sr ; mask all ints
tst.w d0 ; check if DSP L2 hndlr succeeded
bne.s @chkagain ; yes, go check for another
@donelp move (sp)+,sr ; Restore interrupt mask
@noPSCHere
ENDWITH ; {ExpandMemRec, PSC_INT_TBL}
ENDIF
; Check for and dispatch deferred tasks.
; IMPORTANT!! - The following calculation depends on stack setup.
; Change stack usage only with extreme care!
ori.w #$0700,sr ; Block ints from tst of DTskQHdr to jDisptch/RTE
tst.l DTskQHdr ; Are there any deferred tasks in the queued up?
beq.s @NoDTasks ; -> No, just return.
moveq #$07,d0 ; mask for int level in saved SR ($0700)
and.b IntRegsSize(sp),d0 ; test upper byte of saved SR. Are we returning to Level 0?
bne.s @NoDTasks ; -> Yes, run defered tasks (the nominal case)
@DTDispatch movea.l jDisptch,a0 ; get jump vector for deferred task dispatcher
jsr (a0) ; dispatch the deferred tasks
@NoDTasks movem.l (sp)+,IntRegs ; restore registers
UnusedInt RTE ; and return from the interrupt
align alignment
JustRTS RTS ; unused dispatch table entry
;_______________________________________________________________________
;
; Routines: Via1Int / Via2Int - Secondary Interrupt Dispatchers
; Inputs: none
; Outputs: A1 - base address of the interrupting VIA
; Destroys: A0, A1, D0
;
; Function: Decodes and prioritizes VIA interrupts, locates a handler
; for the highest priority enable VIA interrupt source in the Via1DT
; or Via2DT as shown below. The handler is jumped to, and it will return
; to the primary interrupt handler when done.
;
;
; Via1DT/Via2DT -> (00) CA2 highest priority
; (04) CA1 |
; (08) shift reg |
; (0C) CB2 |
; (10) CB1 |
; (14) T2 Timer \|/
; (18) T1 Timer V
; (1C) spurious: no interrupt pending lowest priority
;
; NOTE: The Via2Int routine is also used for RBV interrupts. This is possible
; because the VIA and RBV both have IER and IFR registers whose bits
; have the same meanings. The registers are at different offsets
; on the two chips, but if you .OR. the offsets, you can have common
; code to work with either chip. This is possible because the address
; bits used by the two chips don't overlap, and each chip happens to ignore
; the other chips address bits.
;_______________________________________________________________________
; "standard" VIA1 interrupt dispatcher
align alignment ; align on cache line boundary
Level1Via1Int
movem.l IntRegs,-(SP) ; preserve registers and push return…
pea FinishInt ; …addr so on rts it goes to FinishInt
movea.l VIA,a1 ; get VIA1 base address
moveq.l #$7F,d0 ; mask for interrupt pending bits (clr high bit)
eieioSTP
and.b vIFR(a1),d0 ; get VIA interrupt pending flags
eieioSTP
and.b vIER(a1),d0 ; only process enabled interrupts
eieioSTP
movea.w PrioritizeViaInts(d0.w*2),a0 ; get the dispatch table offset
movea.l (a0),a0 ; get routine address from table
jmp (a0) ; dispatch to routine
; "standard" VIA2/RBV interrupt dispatcher
align alignment ; align on cache line boundary
Level2Via2Int
movem.l IntRegs,-(SP) ; preserve registers and push return…
pea FinishInt ; …addr so on rts it goes to FinishInt
movea.l VIA2RBV,a1 ; get VIA2 or RBV base address
moveq.l #$7F,d0 ; mask for interrupt pending bits (clr high bit)
eieioSTP
and.b Rv2IFR(a1),d0 ; get VIA/RBV interrupt pending flags
eieioSTP
lea Via2DT-Via1DT,A0 ; bias to point to VIA2 interrupt dispatch table
eieioSTP
and.b Rv2IER(a1),d0 ; only process enabled interrupts
eieioSTP
adda.w PrioritizeViaInts(d0.w*2),a0 ; get the dispatch table offset
movea.l (a0),a0 ; get routine address from table
jmp (a0) ; dispatch to routine
IF hasPSC THEN
; VIA2 interrupt dispatcher for PSC
align alignment ; align on cache line boundary
PSCLevel2Via2Int
movem.l IntRegs,-(SP) ; preserve registers and push return…
pea FinishInt ; …addr so on rts it goes to FinishInt
movea.l VIA2,a1 ; get VIA2 base address
moveq.l #$6F,d0 ; mask for interrupt pending bits (clr high bit)
And.b vIFR(a1),d0 ; get VIA/RBV interrupt pending flags
lea Via2DT-Via1DT,A0 ; bias to point to VIA2 interrupt dispatch table
And.b vIER(a1),d0 ; only process enabled interrupts
adda.w PrioritizeViaInts(d0.w*2),a0 ; get the dispatch table offset
movea.l (a0),a0 ; get routine address from table
jmp (a0) ; dispatch to routine
ENDIF ; {hasPSC}
; Priority encoding table, indexed by pending interrupt flag register, and returns
; the interrupt dispatch table address of the highest priority pending interrupt.
; Priority order is bit 0 is highest priority, bit 7 is lowest priority.
align alignment ; align on cache line boundary
PrioritizeViaInts
dc.w Via1DT+(4*7) ; 0 0 0 0 0 0 0 no bits set
dc.w Via1DT+(4*0) ; 0 0 0 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 0 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 0 0 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 0 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 0 0 0 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 0 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 0 0 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 0 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*4) ; 0 0 1 0 0 0 0 bit 4 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 1 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 0 1 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 1 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 0 0 1 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 1 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 0 1 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 1 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*5) ; 0 1 0 0 0 0 0 bit 5 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 0 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 1 0 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 0 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 0 1 0 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 0 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 1 0 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 0 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*4) ; 0 1 1 0 0 0 0 bit 4 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 1 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 1 1 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 1 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 0 1 1 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 1 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 1 1 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 1 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*6) ; 1 0 0 0 0 0 0 bit 6 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 0 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 0 0 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 0 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 1 0 0 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 0 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 0 0 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 0 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*4) ; 1 0 1 0 0 0 0 bit 4 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 1 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 0 1 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 1 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 1 0 1 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 1 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 0 1 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 1 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*5) ; 1 1 0 0 0 0 0 bit 5 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 0 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 1 0 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 0 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 1 1 0 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 0 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 1 0 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 0 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*4) ; 1 1 1 0 0 0 0 bit 4 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 1 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 1 1 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 1 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 1 1 1 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 1 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 1 1 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 1 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 1 1 1 1 bit 0 is highest priority
;_______________________________________________________________________
;
; Routine: SonicInt Level 3 SONIC Ethernet Interrupt Dispatcher
;
; The SONIC Ethernet hardware is logically a slot device, so SonicInt
; simply chains to the appropriate slot handler at this time.
;_______________________________________________________________________
align alignment ; align on cache line boundary
IMPORT RunSlotHandlers
; RunSlotHandlers as if it were a slot #9 interrupt.
Level3SonicInt
movem.l IntRegs,-(SP) ; preserve registers and push return…
pea FinishInt ; …addr so on rts it goes to FinishInt
moveq #9,d0
jmp RunSlotHandlers
IF hasIopScc THEN
;_______________________________________________________________________
; Routine: Level4SccIopInt ... Interrupt Dispatcher
;_______________________________________________________________________
align alignment ; align on cache line boundary
Level4SccIopInt
movem.l IntRegs,-(SP) ; preserve registers and push return…
pea FinishInt ; …addr so on rts it goes to FinishInt
moveq.l #0,d0 ; SCC IOP is IOP number 0
eieioSTP
jmp IOPInterrupt ; handle the interrupt and return
eieioSTP
ENDIF
;_______________________________________________________________________
;
; Routine: SccDecode 8530 SCC Interrupt Dispatcher
;
; All SCC interrupts: This interrupt dispatcher determines the actual
; interrupt source and dispatches through a table of secondary vectors
; maintained in low memory. The table looks like this:
;
; SccDT -> (00) channel B: transmit buffer empty
; (04) channel B: external/status
; (08) channel B: receive character available
; (0C) channel B: special receive condition
; (10) channel A: transmit buffer empty
; (14) channel A: external/status
; (18) channel A: receive character available
; (1C) channel A: special receive condition
;
; SccDT contains a long entry-point address for each of the eight primary
; interrupt routines corresponding to the eight primary interrupting sources.
;
; The two external status interrupts may be broken down into the following
; sources by the primary receiver:
;
; zero count (when the SCC baud rate generator is used as a timer)
; DCD transition
; sync/hunt (for synchronous serial modes only)
; CTS transition (external handshake in signal)
; Tx Underrun/EOM (for synchronous serial modes only)
; Break/abort (interrupts when break(async)/abort(sync) begins and ends)
;
; A secondary dispatch is made for external/status interrupts through
; the external/status dispatch table:
;
; ExtStsDT -> (00) ext/sts B - non-mouse
; (04) unused (formerly mouse vertical interrupt)
; (08) ext/sts A - non-mouse
; (0C) unused (formerly mouse horizontal interrupt)
;
; When dispatching the external/status handler, D0 contains the current
; status (read reg 0) and D1 the changed bits from the previous time
; an extenal/status interrupt was received. A reset ext/sts command is issued.
;
; The two special receive condition interrupts may also be further subdivided.
;
; end of frame (synchronous modes)
; CRC/framing error
; receiver overrun
; parity error
; all sent (asynchronous mode only)
;
; Each primary routine is entered with the processor priority masked, and with
; registers D0-D3 and A0-A3 available for use; A0 will point to SCC channel A/B
; control read address and A1 to SCC channel A/B control write address,
; depending upon which channel is interrupting:
;
; (READ ADDRESS) (WRITE ADDRESS)
;
; CHANNEL A/B DATA 4(A0) 4(A1)
;
; CHANNEL A/B CONTROL (A0) (A1)
;
; Each routine (except for external/status secondary routines) is responsible
; for clearing the source of the interrupt in the SCC, and for saving and
; restoring any additional registers used.
;
; SCC interrupt service routines should return by RTS to this dispatcher.
;
; The interrupt routine is selected by reading the SCC modified interrupt vector.
; The SCC selects the particular vector to supply according to a fixed priority:
;
; Receiver channel A (highest)
; Transmit channel A
; Ext/Status channel A
; Receiver channel B
; Transmit channel B
; Ext/Status channel B (lowest)
;
; The highest priority interrupt which is also enabled is selected by the SCC.
; Only processing one request at a time allows SccDecode to be re-entrant and
; service routines may lower the processor priority as soon as possible in
; order to process other pending interrupts.
;
;
; Optimization Note:
;
; Slower machines exhibit significant serial throughput problems particularly at
; relatively high baud rates. The most significant contribution to this problem
; is the simple overhead of running through the interrupt handler for every
; single character transmitted or received. The effects are most apparent when
; the 24-bit interrupt handler is frequently forced to swap MMU modes because
; SCC interrupts may arrive when the machine is in 32-bit mode.
;
; An interim approach to reducing the apparent problem is to NOT take an interrupt
; for each received character, but rather to empty out the SCC FIFO before returning
; to the primary interrupt dispatcher. This is not a complete solution! System-wide
; interrupt latency is still a problem and the small 3-byte FIFO in the SCC is not
; sufficient to overcome the latency now inherent in the traditional Mac OS.
;
; Relative to earlier versions of this dispatcher, the dispatcher is patched to call
; (i.e. JSR to) the serial driver's interrupt routines, rather than jumping to them.
; The service routine then returns to the secondary dispatcher, which checks to see if
; there is another character available. If there is another character pending, this
; dispatch routine loops to dispatch to the new interrupt (which must now be pending)
; rather than returning to the primary dispatcher (and repeatedly incurring the processor
; interrupt dispatch overhead).
;
; We do this ONLY FOR CHANNEL A, since it's the only one that's documented to be
; fast, and also so that LocalTalk won't pound us at its 230K baud rate.
;
; The Serial Driver Rx and SC interrupt service routines are patched in conjuction
; with this so that if a Device Manager request completes, we exit to the primary
; dispatcher regardless of whether a character is pending. This way we exit the
; interrupt handlers completely at least once per Device Manager request, allowing
; things like deferred tasks to run more in sequence.
;____________________________________________________________________________
align alignment ; align on cache line boundary
Level4SccInt
movem.l IntRegs,-(SP) ; preserve registers and push return…
pea FinishInt ; …addr so on rts it goes to FinishInt
;fall into SccDecode
export SccDecode
SccDecode
MOVE.L SCCRd,A0 ; get SCC read address
MOVE.B (A0),D0 ; read to sync up SCC (just to be safe)
MOVE.L SCCWr,A1 ; get SCC channel B write control address
MOVE.B #2,(A1) ; point to SCC register 2, B channel
LEA SccDT,A2 ; point to dispatch table
MOVEQ #$0E,D0 ; AND mask
AND.B (A0),D0 ; read the modified interrupt vector
CMPI.B #8,D0 ; channel A interrupt?
bge.s GoChannelA ; branch if for A
MOVE.L (A2,D0.W*2),A2 ; get dispatch vector
jmp (A2) ; go run service routine
GoChannelA ADDQ #2,A0 ; adjust SCC addresses for port A
ADDQ #2,A1
MOVE.L (A2,D0.W*2),A2 ; get dispatch vector
jsr (A2) ; call service routine
; If the interrupt finished a Device Mgr request, then return directly to the
; primary interrupt dispatcher, otherwise we return and continue from here.
movea.l SCCRd,a0 ; point to SCC read base address
btst.b #RxCA,2(a0) ; SCC data available on channel A?
bne.s SccDecode ; data available, so dispatch again
SccIntDone rts ; done
;_______________________________________________________________
;
; Secondary Dispatch routines for SCC external status interrupts
;
; On Entry: A0.L = SCC read address (appropriate channel)
; A1.L = SCC write address (appropriate channel)
; D0-D3/A0-A3 have been saved.
;
; On Exit: A0.L, A1.L are still SCC ptrs
; D0.B = SCC RR0 status
; D1.B = SCC RR0 bits which changed since last interrupt
; SCCASts/SCCBSts = updated with new RR0 value
; A2/A3/D2/D3 are undefined.
;_______________________________________________________________
align alignment ; align on cache line boundary
ExtBInt MOVE.B (A0),D0 ; * read SCC RR0 status for channel B
LEA SCCBSts,A3 ; old register value
LEA ExtStsDT,A2 ; point to channel B dispatch vectors
BRA.S ExtABInt ; share some code
align alignment ; align on cache line boundary
ExtAInt MOVE.B (A0),D0 ; * read SCC RR0 status for channel A
LEA SCCASts,A3 ; old register value
LEA ExtStsDT+8,A2 ; point to channel A dispatch vectors
ExtABInt MOVE.B #15,(A1) ; * point to SCC register 15,
; appropriate channel
MOVE.B (A3),D1 ; get old status
MOVE.B D0,(A3) ; update the old
EOR.B D0,D1 ; get changed bits
AND.B (A0),D1 ; * only look at enabled ext/sts bits
MOVE.B #$10,(A1) ; * clear the ext/status interrupt
MOVE.L (A2),A2 ; get the vector
JMP (A2) ; go to it
IF hasPSC THEN
WITH ExpandMemRec, PSC_INT_TBL
;————————————————————————————————————————————————————————————————————————————————
; Routine: Level3PSCInt
;
; Inputs: none
;
; Destroys: D0, D1, A0, A1
;
; Called by: autovectored int
;
; Calls: Level 3 Interrupt handlers, if installed in PSC_INT_TBL
;
; Notes: Does NOT loop like other dispatchers since only servicing
; one int. source.
;————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
Level3PSCInt
movem.l IntRegs,-(sp) ; preserve registers
Move.L UnivInfoPtr, A0 ; get ptr to ProductInfo
Add.L ProductInfo.DecoderInfoPtr(A0), A0 ; point to the base address table
Move.L DecoderInfo.PSCAddr(A0), A0 ; get the PSC base address in A0
Move.l ExpandMem, A1
Move.l emDMADispatchGlobals(A1), A1 ; Get PSC Int. Table base
; PSC feature: read Int. reg until 2 reads produce same result
@chkagain Move.b L3IR(A0), D1 ; get L3 int status
Cmp.b L3IR(A0), D1 ; do they match?
Bne.s @chkagain ; no, read until matches
AndI.b #(1<<MACE), D1
And.b L3IER(A0), D1 ; an enabled int. to service?
beq FinishInt ; no -> check for Deferred Tasks and RTE
@gohandler Move.l MACEhndlr(A1), D0 ; get handler
beq FinishInt ; no -> check for Deferred Tasks and RTE
Move.l D0, A0
Move.l MACEparm(A1), A1 ; get handler's parm
pea FinishInt ; push addr so on rts it goes to FinishInt
jmp (A0) ; call handler
;————————————————————————————————————————————————————————————————————————————————
; Routine: Level4PSCInt
;
; Inputs: none
;
; Destroys: D0, A0, A1
;
; Called by: autovectored int
;
; Calls: Level 4 Interrupt handlers, if installed in PSC_INT_TBL
;
; Notes: All DMA interrupts are handled as if the DMA controller were
; a single device interrupting at level 4. Hence, PSCDMADispatch
; is subordinate to this dispatcher.
;————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
Level4PSCInt
movem.l IntRegs,-(sp) ; preserve registers
MoveM.l A4/A5/D5, -(SP) ; save not-interrupt regs
Move.L UnivInfoPtr, A0 ; get ptr to ProductInfo
Add.L ProductInfo.DecoderInfoPtr(A0), A0 ; point to the base address table
Move.L DecoderInfo.PSCAddr(A0), A5 ; get the PSC base address in A5
Move.l ExpandMem, A4
Move.l emDMADispatchGlobals(A4), A4 ; Get PSC Int. Table base
; PSC feature: read int reg until 2 reads produce same result
@chkagain Move.b L4IR(A5), D5 ; get L4 int status
Cmp.b L4IR(A5), D5 ; do they match?
Bne.s @chkagain ; no, read until matches
; another enabled int. to service?
AndI.b #(1<<L4SCCA)+(1<<L4SCCB)+(1<<SNDSTAT)+(1<<DMA), D5
And.b L4IER(A5), D5
Beq.s @exit ; no, leave
@chkscca BTst #L4SCCA, D5 ; SCCA int?
Beq.s @chksccb ; no
Move.l L4SCCAhndlr(A4), D0 ; get handler
Beq.s @chksccb ; no handler, chk other L4 int sources
Move.l D0, A0
Move.l L4SCCAparm(A4), A1 ; get handler's parm
Jsr (A0) ; call handler
@chksccb BTst #L4SCCB, D5 ; SCCB int?
Beq.s @chksnd ; no
Move.l L4SCCBhndlr(A4), D0 ; get handler
Beq.s @chksnd ; no handler, chk other L4 int sources
Move.l D0, A0
Move.l L4SCCBparm(A4), A1 ; get handler's parm
Jsr (A0) ; call handler
@chksnd BTst #SNDSTAT, D5 ; Singer CODEC sound int?
Beq.s @chkdma ; no
Move.l SNDSTAThndlr(A4), D0 ; get handler
Beq.s @chkdma ; no handler, chk other L4 int sources
Move.l D0, A0
Move.l SNDSTATparm(A4), A1 ; get handler's parm
Jsr (A0) ; call handler
@chkdma BTst #DMA, D5 ; DMA int?
Beq.s @chkagain ; no
Bsr.s PSCDMADispatch ; call dma int dispatcher
; A4,A5 must be initialized
Bra.s @chkagain ; go see if another L4 int. occurred
@exit MoveM.l (SP)+, A4/A5/D5 ; restore non-interrupt regs
bra FinishInt ; check for Deferred Tasks and RTE
;————————————————————————————————————————————————————————————————————————————————
; Routine: PSCDMADispatch
; Loops calling a DMA Interrupt Handler, if installed, for each
; interrupting DMA channel as indicated by the PSC's Interrupt
; Status Register.
;
; Inputs: A5 - PSC base address
; A4 - PSC Interrupt table base address
;
; Destroys: D0,A0,A1
;
; Called by: Level4PSCInt
;
; Calls: DMA channel interrupt handler obtained from PSC Interrupt Table
;————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
PSCDMADispatch
MoveM.l A6/D4/D5, -(SP) ; save non-interrupt regs
Lea DMA_hndlrs(A4),A6 ; get address of start of DMA int hndlrs
; PSC feature: read Int. reg until 2 reads produce same result
@chkagain Move.l PSC_ISR(A5), D5 ; get L4 int enable
Cmp.l PSC_ISR(A5), D5 ; do they match?
Bne.s @chkagain ; no, read until matches
@chkisr BFFFO D5{0:8}, D4 ; get highest pri interrupting channel
Beq.s @noints ; no (more) int sources, leave
Move.l (A6, D4*8), D0 ; get chnl int handler
Beq.s @nextchan
Move.l D0, A0
Move.l 4(A6, D4*8), A1 ; get hndlr's parm
Jsr (A0) ; call chnl int handler
@nextchan BFClr D5{D4:1} ; clear bit in D5 for int just processed
Bra.s @chkisr ; go chk other chnl ints
@noints MoveM.l (SP)+, A6/D4/D5 ; restore non-interrupt regs
RTS
;————————————————————————————————————————————————————————————————————————————————
; Routine: Level5PSCInt
;
; Inputs: none
;
; Destroys: D0, A0, A1
;
; Called by: autovectored int
;
; Calls: Level 5 Interrupt handlers, if installed in PSC_INT_TBL
;————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
Level5PSCInt
movem.l IntRegs,-(sp) ; preserve registers
MoveM.l A4/A5/D5, -(SP) ; save not-interrupt regs
Move.L UnivInfoPtr, A0 ; get ptr to ProductInfo
Add.L ProductInfo.DecoderInfoPtr(A0), A0 ; point to the base address table
Move.L DecoderInfo.PSCAddr(A0), A5 ; get the PSC base address in A5
Move.l ExpandMem, A4
Move.l emDMADispatchGlobals(A4), A4 ; Get PSC Int. Table base
; PSC feature: read int reg until 2 reads produce same result
@chkagain Move.b L5IR(A5), D5 ; get L5 int status
Cmp.b L5IR(A5), D5 ; do they match?
Bne.s @chkagain ; no, read until matches
; another enabled int. to service?
AndI.b #(1<<DSP)+(1<<FRMOVRN), D5
And.b L5IER(A5), D5
Beq.s @exit ; no, leave
@chkdsp BTst #DSP, D5 ; DSP int?
Beq.s @chkfrmovrn ; no
Move.l DSPhndlr(A4), D0 ; get handler
Beq.s @chkfrmovrn ; no handler, chk other L5 int sources
Move.l D0, A0
Move.l DSPparm(A4), A1 ; get handler's parm
Jsr (A0) ; call handler
@chkfrmovrn BTst #FRMOVRN, D5 ; FRMOVRN int?
Beq.s @chkagain ; no
Move.l FRMOVRNhndlr(A4), D0 ; get handler
Beq.s @chkagain ; no handler, loop
Move.l D0, A0
Move.l FRMOVRNparm(A4), A1 ; get handler's parm
Jsr (A0) ; call handler
Bra.s @chkagain ; go see if another L5 int. occurred
@exit MoveM.l (SP)+, A4/A5/D5 ; restore non-interrupt regs
bra FinishInt ; check for Deferred Tasks and RTE
;————————————————————————————————————————————————————————————————————————————————
; Routine: Level6PSCInt
;
; Inputs: none
;
; Destroys: D0, A0, A1
;
; Called by: autovectored int
;
; Calls: Level 6 Interrupt handlers, if installed in PSC_INT_TBL
;————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
Level6PSCInt
movem.l IntRegs,-(sp) ; preserve registers
MoveM.l A4/A5/D5, -(SP) ; save not-interrupt regs
Move.L UnivInfoPtr, A0 ; get ptr to ProductInfo
Add.L ProductInfo.DecoderInfoPtr(A0), A0 ; point to the base address table
Move.L DecoderInfo.PSCAddr(A0), A5 ; get the PSC base address in A5
Move.l ExpandMem, A4
Move.l emDMADispatchGlobals(A4), A4 ; Get PSC Int. Table base
; PSC feature: read int reg until 2 reads produce same result
@chkagain Move.b L6IR(A5), D5 ; get L6 int status
Cmp.b L6IR(A5), D5 ; do they match?
Bne.s @chkagain ; no, read until matches
; another enabled int. to service?
AndI.b #(1<<L660HZ)+(1<<L6SCCA)+(1<<L6SCCB), D5
And.b L6IER(A5), D5
Beq.s @exit ; no, leave
@chk60hz BTst #L660HZ, D5 ; 60.15 HZ int?
Beq.s @chkscca ; no
Move.l L660HZhndlr(A4), D0 ; get handler
Beq.s @chkscca ; no handler, chk other L6 int sources
Move.l D0, A0
Move.l L660HZparm(A4), A1 ; get handler's parm
Jsr (A0) ; call handler
@chkscca BTst #L6SCCA, D5 ; SCC Port A int?
Beq.s @chksccb ; no
Move.l L6SCCAhndlr(A4), D0 ; get handler
Beq.s @chksccb ; no handler, chk other L6 int sources
Move.l D0, A0
Move.l L6SCCAparm(A4), A1 ; get handler's parm
Jsr (A0) ; call handler
@chksccb BTst #L6SCCB, D5 ; SCC Port B int?
Beq.s @chkagain ; no
Move.l L6SCCBhndlr(A4), D0 ; get handler
Beq.s @chkagain ; no handler, loop
Move.l D0, A0
Move.l L6SCCBparm(A4), A1 ; get handler's parm
Jsr (A0) ; call handler
Bra.s @chkagain ; go see if another L6 int. occurred
@exit MoveM.l (SP)+, A4/A5/D5 ; restore non-interrupt regs
bra FinishInt ; check for Deferred Tasks and RTE
ENDWITH ; {ExpandMemRec, PSC_INT_TBL}
ENDIF ; {hasPSC}
IF hasAMIC THEN
WITH ExpandMemRec, DMADispGlobals
;————————————————————————————————————————————————————————————————————————————————
; Routine: Level3AMICInt / PDMMACEHndlr
;
; Called by: autovectored int
;
; Calls: MACE level 3 interrupt handler
;
; Notes: MACE should be the only device interrupting at this level, so
; dispatch to the MACE interrupt handler is unconditional. Also,
; the dispatcher does not loop since consecutive MACE interrupts
; are unlikely.
;————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
Level3AMICInt
movem.l IntRegs,-(SP) ; preserve registers and push return…
pea FinishInt ; …addr so on rts it goes to FinishInt
movea.l ([ExpandMem],emDMADispatchGlobals), A1 ; get dispatch table base address
movea.l maceVector(A1), A0 ; get handler vector from table
movea.l maceRefcon(A1), A1 ; get handler refcon from table
jmp (a0) ; chain through handler
;_____________________________________________________________________________
; Routine: Level4AMICInt / PDMDMAHndlr
;
; Called by: autovectored int
;
; PDM DMA Interrupt Dispatcher
;
; Currently PDM's DMA irq comes in at Level 4. This routine is responsible
; for dispatching to one routine per irq according to the AMIC DMA Irq flag
; registers. Priority has been arbitrarily set according to bit field offsets
; in the flag registers.
;
; PDM's SCC irq is also at level 4, so to reduce SCC irq latency, this routine
; checks for SCC irqs first before looking for DMA interrupts.
;
; The positions in the table define the priority (lower entries are found first).
; The entries in the table are defined as follows (from left to right; highest
; priority to lowest):
;
; SCC | SndOut | SndIn | Unused | Floppy | EnetTx | EnetRx | TxA | RxA | TxB | RxB
;
; Remember the SCC is checked first. It has the highest priority, followed by
; DMA interrupts in the order listed above.
;_____________________________________________________________________________
align alignment ; align on cache line boundary
Level4AMICInt
movem.l IntRegs,-(sp) ; preserve registers
; Check for an SCC interrupt.
@loop btst #2,AMICIrqBase+AMICIrqFlags ; is any SCC interrupt pending (port A or B)?
bne.s @isSCC
; If we're here, then no SCC irq. Dispatch to appropriate DMA handler.
@notSCC move.b AMICIrqBase+AmicDMAFlags1,d0 ; Get the second byte of IRQ flags
lsl.w #8,d0
move.b AMICIrqBase+AmicDMAFlags0,d0 ; Get the first byte of IRQ flags
bfffo d0{22:10},d0 ; Get highest pri interrupting channel
beq FinishInt ; No bits set, -> check for Defrd Tasks and RTE
eori.w #31,d0 ; Make lsb 0 based
@GotOne move.l ([ExpandMem],emDMADispatchGlobals),a0 ; Get the ptr to our globals from expandmem
move.l ddRefCon0(a0,d0*8),a1 ; Load this handler's refCon
move.l ddVector0(a0,d0*8),a0 ;
move.w sr,-(sp)
jsr (A0) ; Call the guy
move.w (sp)+,sr
bra.b @loop ; see if more level 4's pending...
; Got an SCC interrupt.
@isSCC
move.w sr,-(sp)
movea.l ([ExpandMem],emDMADispatchGlobals), A1 ; get dispatch table base address
move.b #2,([SCCWr],bCtl) ; point to SCC register 2, B channel
nop
btst #3,([SCCRd],bCtl) ; test the interrupting channel status bit
bne.s @portA ; bit set for port A
@portB
movea.l SCCLvl4Bvector(A1), A0 ; get handler vector from table
movea.l SCCLvl4Brefcon(A1), A1 ; get handler refcon from table
jsr (A0) ; Call the guy
move.w (sp)+,sr
bra.b @loop ; see if more level 4's pending...
@portA
movea.l SCCLvl4Avector(A1), A0 ; get handler vector from table
movea.l SCCLvl4Arefcon(A1), A1 ; get handler refcon from table
jsr (A0) ; Call the guy
move.w (sp)+,sr
bra.b @loop ; see if more level 4's pending...
ENDWITH ; {ExpandMemRec, DMADispGlobals}
ENDIF ; {hasAMIC}
IF hasGrandCentral THEN
WITH ExpandMemRec, GCInterruptDispatchTable
;————————————————————————————————————————————————————————————————————————————————
; Routine: Level2GCInt
;
; Called by: autovectored interrupt
;
; Calls: level 2 interrupt handlers
;
; Notes: Grand Central does not implement a VIA2, although it reports
; any number of level 2 interrupts.
;————————————————————————————————————————————————————————————————————————————————
gcL2Ints equ 1 << gcifDevSCSI0 |\
1 << gcifDevSCSI1 |\
1 << gcifDevAudio |\
1 << gcifDevSwim3 |\
1 << gcifExtPci0 |\
1 << gcifExtPci1 |\
1 << gcifExtSlot0 |\
1 << gcifExtSlot1 |\
1 << gcifExtSlot2 |\
1 << gcifExtSwatch0 |\
1 << gcifExtSwatch1 |\
1 << gcifExtJivi |\
1 << gcifExtGotham |\
1 << gcifExtSpare
align alignment ; align on cache line boundary
Level2GCInt
movem.l IntRegs,-(sp)
@CheckLevels
movea.l ([ExpandMem],emDMADispatchGlobals),a1 ; get dispatch table base address
movea.l gcBaseAddr(a1),a0 ; get Grand Central base address
move.l #gcL2Ints,d0 ; mask to examine SCC device interrupts
and.l gcInterruptLevels(a0),d0 ; did either SCC channel interrupt?
beq FinishInt
@DispatchL2
bfffo d0{0:32},d0 ; get an index for the first source
eori #31,d0 ; convert bit field offset to bit number
movea.l gcVector(a1,d0.l*8),a0 ; get handler vector from dispatch table
movea.l gcRefCon(a1,d0.l*8),a1 ; get handler refcon from dispatch table
jsr (a0) ; call handler
bra.b @CheckLevels ; loop until no level 2 interrupts pending
;————————————————————————————————————————————————————————————————————————————————
; Routine: Level3GCInt
;
; Called by: autovectored interrupt
;
; Calls: MACE level 3 interrupt handler
;
; Notes: MACE should be the only device interrupting at this level, so
; dispatch to the MACE interrupt handler is unconditional. Also,
; the dispatcher does not loop since consecutive MACE interrupts
; are unlikely.
;————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
Level3GCInt
movem.l IntRegs,-(sp)
pea FinishInt
movea.l ([ExpandMem],emDMADispatchGlobals),a1 ; get dispatch table base address
moveq #gcifDevMACE,d0 ; hard-code index for MACE vector
movea.l gcVector(a1,d0.l*8),a0 ; get handler vector from dispatch table
movea.l gcRefCon(a1,d0.l*8),a1 ; get handler refcon from dispatch table
jmp (a0) ; chain through handler
;————————————————————————————————————————————————————————————————————————————————
; Routine: Level4GCInt
;
; Called by: autovectored interrupt
;
; Calls: SCC and DMA level 4 interrupt handlers
;
; Notes: The SCC device interrupts are examined first in order that they
; may be serviced with higher priority than the other interrupts
; at this level, which are a variety of DMA interrupts.
;————————————————————————————————————————————————————————————————————————————————
gcL4SCCInts equ 1 << gcifDevSccA |\
1 << gcifDevSccB
gcL4DMAInts equ 1 << gcifDmaSCSI0 |\
1 << gcifDmaFloppy |\
1 << gcifDmaEthTx |\
1 << gcifDmaEthRx |\
1 << gcifDmaSccATx |\
1 << gcifDmaSccARx |\
1 << gcifDmaSccBTx |\
1 << gcifDmaSccBRx |\
1 << gcifDmaAudOut |\
1 << gcifDmaAudIn |\
1 << gcifDmaSCSI1
align alignment ; align on cache line boundary
Level4GCInt
movem.l IntRegs,-(sp)
@CheckLevels
movea.l ([ExpandMem],emDMADispatchGlobals),a1 ; get dispatch table base address
movea.l gcBaseAddr(a1),a0 ; get Grand Central base address
move.l gcInterruptLevels(a0),d1 ; take a snapshot of the interrupt levels
move.l #gcL4SCCInts,d0 ; mask to examine SCC device interrupts
and.l d1,d0 ; did either SCC channel interrupt?
bne.b @DispatchL4
move.l #gcL4DMAInts,d0 ; mask to examine DMA channel interrupts
and.l d1,d0 ; did any DMA channel interrupt?
beq FinishInt
@DispatchL4
bfffo d0{0:32},d0 ; get an index for the first source
eori #31,d0 ; convert bit field offset to bit number
movea.l gcVector(a1,d0.l*8),a0 ; get handler vector from dispatch table
movea.l gcRefCon(a1,d0.l*8),a1 ; get handler refcon from dispatch table
jsr (a0) ; call handler
bra.b @CheckLevels ; loop until no level 4 interrupts pending
ENDWITH ; {GCInterruptDispatchTable}
ENDIF ; {hasGrandCentral}
;———————————————————————————————————————————————————————————————————————————————————————
; Routine: InitIntHandler
;
; Inputs: none
;
; Outputs: none
;
; Trashes: D0/A0-A2
;
; Function: Initializes all interrupt vectors and the dispatch tables associated with them.
;
; For 68K systems, this is:
; AutoInt1-AutoInt6 68K interrupt vectors
; Lvl1DT level 1 (VIA1) interrupt dispatch table
; Lvl2DT level 2 interrupt dispatch table (level 4 SCC interrupts)
; ExtStsDT SCC ext/sts secondary dispatch table
; VIA2DT level 2 (VIA2/RBV/...) interrupt dispatch table
;———————————————————————————————————————————————————————————————————————————————————————
align alignment ; align on cache line boundary
export InitIntHandler
InitIntHandler
MOVEA.L UnivInfoPtr,A2 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A2),A2 ; then to the interrupt handlers primitives table,
LEA intFirstVectTbl(A2),A2 ; and finally to the first vectors table
BRA.S @FirstTable
@NextTable MOVEA.L A2,A0 ; point to the start of the table
ADD.L D0,A0
MOVE.L (A0)+,A1 ; get the starting RAM vector address
BRA.S @StartCopy
@CopyToRAM ADD.L A0,D0 ; convert the offset to absolute
MOVE.L D0,(A1)+ ; and copy it to a RAM vector
@StartCopy MOVE.L (A0)+,D0 ; get the next offset; end of table?
BNE.S @CopyToRAM ; -> no, go copy it out
@FirstTable MOVE.L (A2)+,D0 ; get the next table; end of list?
BNE.S @NextTable ; -> no, copy that table
MOVEA.L UnivInfoPtr,A2 ; point to the machine's product info,
ADDA.L IntHandlerPtr(A2),A2 ; then to the interrupt handlers primitives table,
ADDA.L intInitPostProc(A2),A2 ; and finally to the post proc routine
JMP (A2) ; call it
;_______________________________________________________________________
;
; Interrupt Initialization Tables
;
; These are the machine and/or feature specific interrupt tables tied
; to each machine's ProductInfo table in UniversalTables.a. They point
; to routines to turn interrupt sources on and off, and to set up the
; main interrupt vectors, plus any dispatch tables associated with a
; particular interrupt level.
;_______________________________________________________________________
; "standard" level 1-6 interrupt handlers vector table
StdAutoInts DC.L AutoInt1 ; starting vector address
DC.L Level1Via1Int-(*+4) ; level 1 interrupt handler
DC.L Level2Via2Int-(*+4) ; level 2 interrupt handler
DC.L UnusedInt-(*+4) ; level 3 interrupt handler
DC.L Level4SccInt-(*+4) ; level 4 interrupt handler
DC.L UnusedInt-(*+4) ; level 5 interrupt handler
DC.L UnusedInt-(*+4) ; level 6 interrupt handler
DC.L 0 ; end of table
; level 1-6 interrupt handlers vector table for machines with a SONIC chip
SONICAutoInts
DC.L AutoInt1 ; starting vector address
DC.L Level1Via1Int-(*+4) ; level 1 interrupt handler
DC.L Level2Via2Int-(*+4) ; level 2 interrupt handler
DC.L Level3SonicInt-(*+4) ; level 3 interrupt handler
DC.L Level4SccInt-(*+4) ; level 4 interrupt handler
DC.L UnusedInt-(*+4) ; level 5 interrupt handler
DC.L UnusedInt-(*+4) ; level 6 interrupt handler
DC.L 0 ; end of table
; "standard" Lvl1DT and Lvl2DT vectors table
StdLvl12DT DC.L Lvl1DT ; starting vector address
; Lvl1DT starts here
DC.L OneSecInt-(*+4) ; VIA1 CA2 interrupt handler --- jOneSecInt
DC.L VBLInt-(*+4) ; VIA1 CA1 interrupt handler --- jVBLInt
DC.L JustRTS-(*+4) ; VIA1 SR interrupt handler --- jKbdADBInt
DC.L JustRTS-(*+4) ; VIA1 CB2 interrupt handler
DC.L JustRTS-(*+4) ; VIA1 CB1 interrupt handler
DC.L JustRTS-(*+4) ; VIA1 T2 interrupt handler
DC.L JustRTS-(*+4) ; VIA1 T1 interrupt handler
DC.L JustRTS-(*+4) ; VIA1 "any" interrupt handler
; Lvl2DT starts here
DC.L JustRTS-(*+4) ;
DC.L ExtBInt-(*+4) ; SCC channel B external/status interrupt
DC.L JustRTS-(*+4) ;
DC.L JustRTS-(*+4) ;
DC.L JustRTS-(*+4) ;
DC.L ExtAInt-(*+4) ; SCC channel A external/status interrupt
DC.L JustRTS-(*+4) ;
DC.L JustRTS-(*+4) ;
DC.L 0 ; end of table
; "standard" secondary dispatch vectors for SCC interrupts
StdExtStsDT DC.L ExtStsDT ; starting vector address
DC.L JustRTS-(*+4) ;
DC.L JustRTS-(*+4) ;
DC.L JustRTS-(*+4) ;
DC.L JustRTS-(*+4) ;
DC.L 0 ; end of table
; dispatch vectors for VIA2 interrupts with various incarnations of VIA2
IMPORT VIA2SlotInt
StdVIA2DT DC.L Via2DT ; starting vector address
DC.L JustRTS-(*+4) ; VIA2 CA2 interrupt handler
DC.L VIA2SlotInt-(*+4) ; VIA2 CA1 interrupt handler --- jSlotInt
DC.L JustRTS-(*+4) ; VIA2 SR interrupt handler
DC.L JustRTS-(*+4) ; VIA2 CB2 interrupt handler --- jSCSIIrqInt
DC.L JustRTS-(*+4) ; VIA2 CB1 interrupt handler --- jASCInt
DC.L JustRTS-(*+4) ; VIA2 T2 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 T1 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 "any" interrupt handler
DC.L 0 ; end of table
IF hasRBV THEN
IMPORT RbvSlotInt
RBVVIA2DT DC.L Via2DT ; starting vector address
DC.L JustRTS-(*+4) ; VIA2 CA2 interrupt handler
DC.L RbvSlotInt-(*+4) ; VIA2 CA1 interrupt handler --- jSlotInt
DC.L JustRTS-(*+4) ; VIA2 SR interrupt handler
DC.L JustRTS-(*+4) ; VIA2 CB2 interrupt handler --- jSCSIIrqInt
DC.L JustRTS-(*+4) ; VIA2 CB1 interrupt handler --- jASCInt
DC.L JustRTS-(*+4) ; VIA2 T2 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 T1 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 "any" interrupt handler
DC.L 0 ; end of table
ENDIF
IF hasDAFB THEN
IMPORT DAFBVIA2SlotInt
DAFBVIA2DT
DC.L Via2DT ; starting vector address
DC.L JustRTS-(*+4) ; VIA2 CA2 interrupt handler
DC.L DAFBVIA2SlotInt-(*+4) ; VIA2 CA1 interrupt handler --- jSlotInt
DC.L JustRTS-(*+4) ; VIA2 SR interrupt handler
DC.L JustRTS-(*+4) ; VIA2 CB2 interrupt handler --- jSCSIIrqInt
DC.L JustRTS-(*+4) ; VIA2 CB1 interrupt handler --- jASCInt
DC.L JustRTS-(*+4) ; VIA2 T2 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 T1 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 "any" interrupt handler
DC.L 0 ; end of table
ENDIF
; This table is provided for the InfoUnknownUnknown ProductInfo table in UniversalTables.a
; When that table goes away, this one can too...
EXPORT VIAIntTbl
DC.W 0 ; flags
DC.W (VIAIntTblEnd-VIAIntTbl)/4 ; number of entries in the table
VIAIntTbl
DC.L JustRTS-VIAIntTbl ; initialization post proc routine
DC.L VIADisableIntSources-VIAIntTbl ; disable interrupt sources
DC.L VIAEnableOneSecInts-VIAIntTbl ; enable one second interrupts
DC.L VIAEnableSlotInts-VIAIntTbl ; enable slot interrupts
DC.L VIAEnableSoundInts-VIAIntTbl ; enable sound interrupts
DC.L VIADisableSoundInts-VIAIntTbl ; disable sound interrupts
DC.L VIAClearSoundInts-VIAIntTbl ; clear sound interrupts
DC.L VIAEnableSCSIInts-VIAIntTbl ; enable SCSI interrupts
DC.L VIADisableSCSIInts-VIAIntTbl ; disable SCSI interrupts
DC.L VIAClearSCSIInts-VIAIntTbl ; clear SCSI interrupts
DC.L VIAPowerOff-VIAIntTbl ; power off code
DC.L StdAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L StdVIA2DT-(*+4) ; offset to VIA2 dispatch vectors table
DC.L 0 ; end of list
VIAIntTblEnd
IF hasRBV AND hasEgret THEN
EXPORT RBVEgretIntTbl
DC.W 0 ; flags
DC.W (RBVEgretIntTblEnd-RBVEgretIntTbl)/4 ; number of entries in the table
RBVEgretIntTbl
DC.L JustRTS-RBVEgretIntTbl ; initialization post proc routine
DC.L VIADisableIntSources-RBVEgretIntTbl ; disable interrupt sources
DC.L EgretEnableOneSecInts-RBVEgretIntTbl ; enable one second interrupts
DC.L VIAEnableSlotInts-RBVEgretIntTbl ; enable slot interrupts
DC.L VIAEnableSoundInts-RBVEgretIntTbl ; enable sound interrupts
DC.L VIADisableSoundInts-RBVEgretIntTbl ; disable sound interrupts
DC.L VIAClearSoundInts-RBVEgretIntTbl ; clear sound interrupts
DC.L JustRTS-RBVEgretIntTbl ; don't enable SCSI interrupts
DC.L VIADisableSCSIInts-RBVEgretIntTbl ; disable SCSI interrupts
DC.L VIAClearSCSIInts-RBVEgretIntTbl ; clear SCSI interrupts
DC.L EgretPowerOff-RBVEgretIntTbl ; power off code
DC.L StdAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L RBVVIA2DT-(*+4) ; offset to VIA2 dispatch vectors table
DC.L 0 ; end of list
RBVEgretIntTblEnd
ENDIF ; {hasRBV}
IF hasOrwell THEN
EXPORT Quadra700IntTbl, Quadra900IntTbl
DC.W 0 ; flags
DC.W (Quadra700IntTblEnd-Quadra700IntTbl)/4 ; number of entries in the table
Quadra700IntTbl
DC.L JustRTS-Quadra700IntTbl ; initialization post proc routine
DC.L VIADisableIntSources-Quadra700IntTbl ; disable interrupt sources
DC.L VIAEnableOneSecInts-Quadra700IntTbl ; enable one second interrupts
DC.L VIAEnableSlotInts-Quadra700IntTbl ; enable slot interrupts
DC.L VIAEnableSoundInts-Quadra700IntTbl ; enable sound interrupts
DC.L VIADisableSoundInts-Quadra700IntTbl ; disable sound interrupts
DC.L VIAClearSoundInts-Quadra700IntTbl ; clear sound interrupts
DC.L VIAEnableSCSIInts-Quadra700IntTbl ; enable SCSI interrupts
DC.L VIADisableSCSIInts-Quadra700IntTbl ; disable SCSI interrupts
DC.L VIAClearSCSIInts-Quadra700IntTbl ; clear SCSI interrupts
DC.L VIAPowerOff-Quadra700IntTbl ; power off code
DC.L SONICAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L DAFBVIA2DT-(*+4) ; offset to VIA2 dispatch vectors table
DC.L 0 ; end of list
Quadra700IntTblEnd
DC.W 0 ; flags
DC.W (Quadra900IntTblEnd-Quadra900IntTbl)/4 ; number of entries in the table
Quadra900IntTbl
DC.L JustRTS-Quadra900IntTbl ; initialization post proc routine
DC.L VIADisableIntSources-Quadra900IntTbl ; disable interrupt sources
DC.L EgretEnableOneSecInts-Quadra900IntTbl ; enable one second interrupts
DC.L VIAEnableSlotInts-Quadra900IntTbl ; enable slot interrupts
DC.L VIAEnableSoundInts-Quadra900IntTbl ; enable sound interrupts
DC.L VIADisableSoundInts-Quadra900IntTbl ; disable sound interrupts
DC.L VIAClearSoundInts-Quadra900IntTbl ; clear sound interrupts
DC.L VIAEnableSCSIInts-Quadra900IntTbl ; enable SCSI interrupts
DC.L VIADisableSCSIInts-Quadra900IntTbl ; disable SCSI interrupts
DC.L VIAClearSCSIInts-Quadra900IntTbl ; clear SCSI interrupts
DC.L EgretPowerOff-Quadra900IntTbl ; power off code
DC.L Quadra900AutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L Quadra900VIA2DT-(*+4) ; offset to VIA2 dispatch vectors table
DC.L 0 ; end of list
Quadra900IntTblEnd
Quadra900AutoInts
DC.L AutoInt1 ; starting vector address
DC.L Level1Via1Int-(*+4) ; level 1 interrupt handler
DC.L Level2Via2Int-(*+4) ; level 2 interrupt handler
DC.L Level3SonicInt-(*+4) ; level 3 interrupt handler
DC.L Level4SccIopInt-(*+4) ; level 4 interrupt handler
DC.L UnusedInt-(*+4) ; level 5 interrupt handler
DC.L UnusedInt-(*+4) ; level 6 interrupt handler
DC.L 0 ; end of table
Quadra900VIA2DT
DC.L Via2DT ; starting vector address
DC.L SwimIopIntVIA-(*+4) ; VIA2 CA2 interrupt handler
DC.L DAFBVIA2SlotInt-(*+4) ; VIA2 CA1 interrupt handler --- jSlotInt
DC.L JustRTS-(*+4) ; VIA2 SR interrupt handler
DC.L JustRTS-(*+4) ; VIA2 CB2 interrupt handler --- jSCSIIrqInt
DC.L JustRTS-(*+4) ; VIA2 CB1 interrupt handler --- jASCInt
DC.L JustRTS-(*+4) ; VIA2 T2 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 T1 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 "any" interrupt handler
DC.L 0 ; end of table
ENDIF ; {hasOrwell}
IF hasJaws THEN
EXPORT JawsIntTbl
DC.W 0 ; flags
DC.W (JawsIntTblEnd-JawsIntTbl)/4 ; number of entries in the table
JawsIntTbl DC.L JustRTS-JawsIntTbl ; initialization post proc routine
DC.L VIADisableIntSources-JawsIntTbl ; disable interrupt sources
DC.L VIAEnableOneSecInts-JawsIntTbl ; enable one second interrupts
DC.L VIAEnableSlotInts-JawsIntTbl ; enable slot interrupts
DC.L VIAEnableSoundInts-JawsIntTbl ; enable sound interrupts
DC.L VIADisableSoundInts-JawsIntTbl ; disable sound interrupts
DC.L VIAClearSoundInts-JawsIntTbl ; clear sound interrupts
DC.L VIAEnableSCSIInts-JawsIntTbl ; enable SCSI interrupts
DC.L VIADisableSCSIInts-JawsIntTbl ; disable SCSI interrupts
DC.L VIAClearSCSIInts-JawsIntTbl ; clear SCSI interrupts
DC.L PMgrPowerOff-JawsIntTbl ; power off code
DC.L StdAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L StdVIA2DT-(*+4) ; offset to VIA2 dispatch vectors table
DC.L 0 ; end of list
JawsIntTblEnd
ENDIF ; {hasNiagra}
IF hasNiagra THEN
EXPORT NiagraIntTbl
IMPORT NiagraVIA2SlotInt
DC.W 0 ; flags
DC.W (NiagraIntTblEnd-NiagraIntTbl)/4 ; number of entries in the table
NiagraIntTbl
DC.L JustRTS-NiagraIntTbl ; initialization post proc routine
DC.L VIADisableIntSources-NiagraIntTbl ; disable interrupt sources
DC.L VIAEnableOneSecInts-NiagraIntTbl ; enable one second interrupts
DC.L VIAEnableSlotInts-NiagraIntTbl ; enable slot interrupts
DC.L VIAEnableSoundInts-NiagraIntTbl ; enable sound interrupts
DC.L VIADisableSoundInts-NiagraIntTbl ; disable sound interrupts
DC.L VIAClearSoundInts-NiagraIntTbl ; clear sound interrupts
DC.L VIAEnableSCSIInts-NiagraIntTbl ; enable SCSI interrupts
DC.L VIADisableSCSIInts-NiagraIntTbl ; disable SCSI interrupts
DC.L VIAClearSCSIInts-NiagraIntTbl ; clear SCSI interrupts
DC.L PMgrPowerOff-NiagraIntTbl ; power off code
DC.L StdAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L NiagraVIA2DT-(*+4) ; offset to VIA2 dispatch vectors table
DC.L 0 ; end of list
NiagraIntTblEnd
NiagraVIA2DT
DC.L Via2DT ; starting vector address
DC.L JustRTS-(*+4) ; VIA2 CA2 interrupt handler
DC.L NiagraVIA2SlotInt-(*+4) ; VIA2 CA1 interrupt handler --- jSlotInt
DC.L JustRTS-(*+4) ; VIA2 SR interrupt handler
DC.L JustRTS-(*+4) ; VIA2 CB2 interrupt handler --- jSCSIIrqInt
DC.L JustRTS-(*+4) ; VIA2 CB1 interrupt handler --- jASCInt
DC.L JustRTS-(*+4) ; VIA2 T2 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 T1 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 "any" interrupt handler
DC.L 0 ; end of table
ENDIF ; {hasNiagra}
IF hasMSC THEN
EXPORT MSCIntTbl
DC.W 0 ; flags
DC.W (MSCIntTblEnd-MSCIntTbl)/4 ; number of entries in the table
MSCIntTbl DC.L JustRTS-MSCIntTbl ; initialization post proc routine
DC.L VIADisableIntSources-MSCIntTbl ; disable interrupt sources
DC.L VIAEnableOneSecInts-MSCIntTbl ; enable one second interrupts
DC.L VIAEnableSlotInts-MSCIntTbl ; enable slot interrupts
DC.L VIAEnableSoundInts-MSCIntTbl ; enable sound interrupts
DC.L VIADisableSoundInts-MSCIntTbl ; disable sound interrupts
DC.L VIAClearSoundInts-MSCIntTbl ; clear sound interrupts
DC.L JustRTS-MSCIntTbl ; don't enable SCSI interrupts
DC.L VIADisableSCSIInts-MSCIntTbl ; disable SCSI interrupts
DC.L VIAClearSCSIInts-MSCIntTbl ; clear SCSI interrupts
DC.L PMgrPowerOff-MSCIntTbl ; power off code
DC.L StdAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L RBVVIA2DT-(*+4) ; offset to VIA2 dispatch vectors table
DC.L 0 ; end of list
MSCIntTblEnd
ENDIF ; {hasMSC}
IF hasPratt THEN
EXPORT PrattIntTbl
DC.W 0 ; flags
DC.W (PrattIntTblEnd-PrattIntTbl)/4 ; number of entries in the table
PrattIntTbl DC.L JustRTS-PrattIntTbl ; initialization post proc routine
DC.L VIADisableIntSources-PrattIntTbl ; disable interrupt sources
DC.L VIAEnableOneSecInts-PrattIntTbl ; enable one second interrupts
DC.L VIAEnableSlotInts-PrattIntTbl ; enable slot interrupts
DC.L VIAEnableSoundInts-PrattIntTbl ; enable sound interrupts
DC.L VIADisableSoundInts-PrattIntTbl ; disable sound interrupts
DC.L VIAClearSoundInts-PrattIntTbl ; clear sound interrupts
DC.L VIAEnableSCSIInts-PrattIntTbl ; don't enable SCSI interrupts
DC.L VIADisableSCSIInts-PrattIntTbl ; disable SCSI interrupts
DC.L VIAClearSCSIInts-PrattIntTbl ; clear SCSI interrupts
DC.L PMgrPowerOff-PrattIntTbl ; power off code
DC.L StdAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L StdVIA2DT-(*+4) ; offset to VIA2 dispatch vectors table (for now)
DC.L 0 ; end of list
PrattIntTblEnd
ENDIF ; {hasPratt}
IF hasSonora THEN
EXPORT SonoraIntTbl
DC.W 0 ; flags
DC.W (SonoraIntTblEnd-SonoraIntTbl)/4 ; number of entries in the table
SonoraIntTbl
DC.L JustRTS-SonoraIntTbl ; initialization post proc routine
DC.L VIADisableIntSources-SonoraIntTbl ; disable interrupt sources
DC.L EgretEnableOneSecInts-SonoraIntTbl ; enable one second interrupts
DC.L VIAEnableSlotInts-SonoraIntTbl ; enable slot interrupts
DC.L VIAEnableSoundInts-SonoraIntTbl ; enable sound interrupts
DC.L VIADisableSoundInts-SonoraIntTbl ; disable sound interrupts
DC.L VIAClearSoundInts-SonoraIntTbl ; clear sound interrupts
DC.L VIAEnableSCSIInts-SonoraIntTbl ; enable SCSI interrupts
DC.L VIADisableSCSIInts-SonoraIntTbl ; disable SCSI interrupts
DC.L VIAClearSCSIInts-SonoraIntTbl ; clear SCSI interrupts
DC.L EgretPowerOff-SonoraIntTbl ; power off code
DC.L SONICAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L RBVVIA2DT-(*+4) ; offset to VIA2 dispatch vectors table
DC.L 0 ; end of list
SonoraIntTblEnd
ENDIF ; {hasSonora}
IF hasDJMEMC THEN
EXPORT DJMEMCIntTbl
DC.W 0 ; flags
DC.W (DJMEMCIntTblEnd-DJMEMCIntTbl)/4 ; number of entries in the table
DJMEMCIntTbl
DC.L JustRTS-DJMEMCIntTbl ; initialization post proc routine
DC.L VIADisableIntSources-DJMEMCIntTbl ; disable interrupt sources
DC.L VIAEnableOneSecInts-DJMEMCIntTbl ; enable one second interrupts
DC.L VIAEnableSlotInts-DJMEMCIntTbl ; enable slot interrupts
DC.L VIAEnableSoundInts-DJMEMCIntTbl ; enable sound interrupts
DC.L VIADisableSoundInts-DJMEMCIntTbl ; disable sound interrupts
DC.L VIAClearSoundInts-DJMEMCIntTbl ; clear sound interrupts
DC.L VIAEnableSCSIInts-DJMEMCIntTbl ; enable SCSI interrupts
DC.L VIADisableSCSIInts-DJMEMCIntTbl ; disable SCSI interrupts
DC.L VIAClearSCSIInts-DJMEMCIntTbl ; clear SCSI interrupts
DC.L VIAPowerOff-DJMEMCIntTbl ; power off code
DC.L SONICAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L DAFBVIA2DT-(*+4) ; offset to VIA2 dispatch vectors table
DC.L 0 ; end of list
DJMEMCIntTblEnd
ENDIF ; {hasDJMEMC}
IF hasPSC THEN
EXPORT PSCIntTbl
IMPORT PSCVIA2SlotInt
DC.W 0 ; flags
DC.W (PSCIntTblEnd-PSCIntTbl)/4 ; number of entries in the table
PSCIntTbl
DC.L PSCInitPostProc-PSCIntTbl ; initialization post proc routine
DC.L PSCDisableIntSources-PSCIntTbl ; disable interrupt sources
DC.L EgretEnableOneSecInts-PSCIntTbl ; enable one second interrupts
DC.L PSCEnableSlotInts-PSCIntTbl ; enable slot interrupts
DC.L JustRTS-PSCIntTbl ; enable sound interrupts
DC.L JustRTS-PSCIntTbl ; disable sound interrupts
DC.L JustRTS-PSCIntTbl ; clear sound interrupts
DC.L PSCEnableSCSIInts-PSCIntTbl ; enable SCSI interrupts
DC.L PSCDisableSCSIInts-PSCIntTbl ; disable SCSI interrupts
DC.L JustRTS-PSCIntTbl ; clear SCSI interrupts (must be cleared at source)
DC.L EgretPowerOff-PSCIntTbl ; power off code
DC.L PSCAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L PSCVIA2DT-(*+4) ; offset to VIA2 dispatch vectors table
DC.L 0 ; end of list
PSCIntTblEnd
PSCAutoInts DC.L AutoInt1 ; starting vector address
DC.L Level1Via1Int-(*+4) ; level 1 interrupt handler
DC.L PSCLevel2Via2Int-(*+4) ; level 2 interrupt handler
DC.L Level3PSCInt-(*+4) ; level 3 interrupt handler
DC.L Level4PSCInt-(*+4) ; level 4 interrupt handler
DC.L Level5PSCInt-(*+4) ; level 5 interrupt handler
DC.L Level6PSCInt-(*+4) ; level 6 interrupt handler
DC.L 0 ; end of table
PSCVIA2DT DC.L Via2DT ; starting vector address
DC.L JustRTS-(*+4) ; VIA2 CA2 interrupt handler
DC.L PSCVIA2SlotInt-(*+4) ; VIA2 CA1 interrupt handler --- jSlotInt
DC.L JustRTS-(*+4) ; VIA2 SR interrupt handler --- MUNI (NuBus cntrlr)
DC.L JustRTS-(*+4) ; VIA2 CB2 interrupt handler --- jSCSIIrqInt
DC.L JustRTS-(*+4) ; VIA2 CB1 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 T2 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 T1 interrupt handler
DC.L JustRTS-(*+4) ; VIA2 "any" interrupt handler
DC.L 0 ; end of table
ENDIF ; {hasPSC}
IF hasHMC THEN
EXPORT AMICIntTbl
DC.W 0 ; flags
DC.W (AMICIntTblEnd-AMICIntTbl)/4 ; number of entries in the table
AMICIntTbl
DC.L AMICInitPostProc-AMICIntTbl ; initialization post proc routine
DC.L AMICDisableIntSources-AMICIntTbl ; disable interrupt sources
DC.L EgretEnableOneSecInts-AMICIntTbl ; enable one second interrupts
DC.L VIAEnableSlotInts-AMICIntTbl ; enable slot interrupts
DC.L VIAEnableSoundInts-AMICIntTbl ; enable sound interrupts
DC.L VIADisableSoundInts-AMICIntTbl ; disable sound interrupts
DC.L VIAClearSoundInts-AMICIntTbl ; clear sound interrupts
DC.L JustRTS-AMICIntTbl ; don't enable SCSI interrupts
DC.L VIADisableSCSIInts-AMICIntTbl ; disable SCSI interrupts
DC.L VIAClearSCSIInts-AMICIntTbl ; clear SCSI interrupts
DC.L EgretPowerOff-AMICIntTbl ; power off code
DC.L AMICAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L RBVVIA2DT-(*+4) ; offset to VIA2 dispatch vectors table
DC.L 0 ; end of list
AMICIntTblEnd
AMICAutoInts
DC.L AutoInt1 ; starting vector address
DC.L Level1Via1Int-(*+4) ; level 1 interrupt handler
DC.L Level2Via2Int-(*+4) ; level 2 interrupt handler
DC.L Level3AMICInt-(*+4) ; level 3 interrupt handler
DC.L Level4AMICInt-(*+4) ; level 4 interrupt handler
DC.L UnusedInt-(*+4) ; level 5 interrupt handler
DC.L UnusedInt-(*+4) ; level 6 interrupt handler
DC.L 0 ; end of table
ENDIF ; {hasAMIC}
IF hasGrandCentral THEN
EXPORT GCIntTbl
DC.W 0 ; flags
DC.W (GCIntTblEnd-GCIntTbl)/4 ; number of entries in the table
GCIntTbl
DC.L GCInitPostProc-GCIntTbl ; initialization post proc routine
DC.L GCDisableIntSources-GCIntTbl ; disable interrupt sources
DC.L EgretEnableOneSecInts-GCIntTbl ; enable one second interrupts
DC.L JustRTS-GCIntTbl ; enable slot interrupts
DC.L GCEnableSoundInts-GCIntTbl ; enable sound interrupts
DC.L GCDisableSoundInts-GCIntTbl ; disable sound interrupts
DC.L JustRTS-GCIntTbl ; clear sound interrupts
DC.L GCEnableSCSIInts-GCIntTbl ; enable SCSI interrupts
DC.L GCDisableSCSIInts-GCIntTbl ; disable SCSI interrupts
DC.L JustRTS-GCIntTbl ; clear SCSI interrupts
DC.L EgretPowerOff-GCIntTbl ; power off code
DC.L GCAutoInts-(*+4) ; offset to interrupt vectors table
DC.L StdLvl12DT-(*+4) ; offset to level 1 and 2 dispatch vectors table
DC.L StdExtStsDT-(*+4) ; offset to secondary SCC dispatch vectors table
DC.L 0 ; end of list
GCIntTblEnd
GCAutoInts
DC.L AutoInt1 ; starting vector address
DC.L Level1Via1Int-(*+4) ; level 1 interrupt handler
DC.L Level2GCInt-(*+4) ; level 2 interrupt handler
DC.L Level3GCInt-(*+4) ; level 3 interrupt handler
DC.L Level4GCInt-(*+4) ; level 4 interrupt handler
DC.L UnusedInt-(*+4) ; level 5 interrupt handler
DC.L UnusedInt-(*+4) ; level 6 interrupt handler
DC.L 0 ; end of table
ENDIF ; {hasGrandCentral}
ENDWITH ; {ProductInfo, InterruptPrims}
END