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

2861 lines
120 KiB
Plaintext
Raw Normal View History

2019-06-29 15:17:50 +00:00
;__________________________________________________________________________________________________
;
; File: Universal.a
;
; Contains: This module provides Data structures and routines to support Universal ROMs.
; It can also be used in Non-Universal ROMs to provide tables for initializing
; base addresses and hardware.
;
; Written by: Gary G. Davidian
;
; Copyright © 1989-1993 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <SM62> 12/17/93 PN Fix the test for Pratt decoder
; <SM61> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
; machines.
; <SM60> 12/7/93 BG Modified the Frigidaire entries in the djMEMC @MachineTbl to
; properly reflect the VIA PortA values for CPU ID+Speed.
; <SM59> 11/17/93 KW forSTP601 in GetCPUIDReg to or in Risc product to the id.
; <SM58> 11/9/93 KW made some changes for STP machines. changes are conditionalized
; by forSTP601
; <SM57> 9/26/93 KW (H35 BG) Modified the djMEMC memory controller setup so that it
; chooses between Wombats and Speedbumped Wombats and initializes
; the memory controller to use a different set of wait states for
; the Speedbumped machines. This is because the Speedbump'ed
; units do not want to have to use faster-speed DRAM, which
; currently the Quadra 800 (Wombat33inFridge) requires. The
; Speedbumped 650 (Wombat33inLego) will expect 80ns DRAM, just as
; the Centris650 (Wombat25inLego) did.
; <SM56> 8/13/93 KW adding two more smurf wombats
; <SM55> 8/12/93 BG Changed various Cyclone-related boxflags to their official
; names.
; <SM54> 8/11/93 KW made the forSmurf check in GetCPUIDReg dynamic. Currently
; recoginizes Quadra700/900/950 and Centris610/650 quadra800
; <SM53> 7/27/93 GMR Added routine to do a runtime check for BART (on PDM).
; <SM52> 7/2/93 PN Add conditional for export hasCPUIDregs
; <SM51> 6/29/93 SAM (PDW) Added code to check for a cf96 in GetCPUID (for
; PDM/ColdFusion).
; <SM50> 6/14/93 kc Roll in Ludwig.
; <LW7> 4/29/93 fau Updated the Cyclone/Tempest timing to 120ns ROMS for final
; shipment.
; <SM49> 6/3/93 SAM Exporting GetCPUIDReg.
; <SM48> 5/10/93 SAM Added a few nops in the PDM specific CPU ID check.
; <SM46> 4/26/93 RC Get ride of warning due to bra.s
; <SM45> 4/21/93 joe Added hack to GetCPUIDReg for PDM EVT2. (CPUID register doesn't
; work right, so use extra bits in SCSI DMA Ctl reg to check for
; AMIC2.)
; <SM44> 4/20/93 joe Added to PDM-style CPUID reg check. The old
; long-word-access-only code would read the register, write some
; value back, and re-read the register, making sure that the
; second read yielded the same data as the first. The PDM-style,
; byte-access CPUID register read code now does this too.
; <SM43> 4/20/93 jb Fixed up the code to work on either a normal or PDM-style CPUID
; register.
; <SM42> 3/31/93 chp Synchronize SuperMario with changes from <LW5>.
; <LW5> 2/26/93 fau Removed support for Cyclone EVT3 and changed all labels having
; MMC with YMCA.
; <SM41> 2/23/93 RB Fixed a check for djMEMC in InitVIAs where it was depending on
; d3 which wasn't set up. Now checking decoder kind in the low
; byte of d2.
; <SM40> 2/8/93 rab Rolled in the following change from Horror for Wombat: <H30>
; 11/18/92 BG Modified TestForSonic so that instead of just
; reading a register at SonicBase to determine if Sonic is
; present, we actually WRITE a SW Reset command to Sonic. This
; way, not only do we detect it, but we make sure Sonic is always
; reset when booting/restarting.
; <SM39> 1/15/93 PN In case of Quadra 900 which has a Caboose chip, we do not
; execute the DoEgretInit but do a CudaDone otherwise we kill
; Quadra900.
; <SM38> 01/09/93 RM/HY Disable asynchronous messages on Egret based machines. This
; fixes a problem which could potentially causes hangs to occurr
; on restart if enough time elapses before Egret can respond to
; these messages.
; <SM37> 12/23/92 RC Added Support for Smurf on Wombat
; <SM36> 12/17/92 RB Removed some of the LC930 conditionals. Added back other hasXXXX
; conditionals to make it easier to build 1 off 1 Meg ROMs.
; <SM35> 12/11/92 FU Was always checking BoxCyclone33 when programming the YMCA.
; <SM34> 12/4/92 fau Added support for Cyclone40 and Tempest33.
; <SM33> 11/20/92 fau Didn't put a ; on one of my comments.
; <SM32> 11/20/92 fau Added a TestForMUNI to GetExtHardwareInfo so that Tempest can
; check whether the Nubus adapter is there or not. Programmed
; MUNI for Tempest.
; <SM31> 11/7/92 rab Roll in Horror changes. Comments follow:
; <H29> 8/10/92 SWC Fixed the MSC VIA/RBV initialization to disable slot interrupts.
; <H28> 7/2/92 ag Change initial state of the Jaws/dart via2 modemRst bit. It
; should be 0 to insure the modem is in reset when not in use.
; This also avoids current leakage to the modem.
; <H27> 6/25/92 CCH Added conditionalized support for Quadra on RISC-based emulator.
; <H26> 6/4/92 HY Add ptr to sound primitives vector table in LC product info table.
; <H25> 6/3/92 BG Conditionally changed -InitVIAs- temporarily to build the
; correct sequence of code for the BIOS1 chip on Wombat til BIOS
; is revved to have VIA1 work correctly. This change only takes
; effect if you Build -p -WombatEVT1.
; <H24> 5/28/92 NJV Added SoundPlayAndRecord bit to ProductInfo Tables of machines
; that can play and record simultaneously.
; <H22> 05-18-92 jmp Changed the “sRsrcZydecoDir” name to the more generic
; “sRsrcBFBasedDir” (BF=BoxFlag) name.
; <H18> 5/3/92 BG Removed references to hasOrwell2, since it is now superfluous to
; hasOrwell.
; <H17> 4/24/92 HJR Added CheckForNiagra so that we may distinguish from
; Jawsdecoder.
; <SM30> 11/3/92 SWC Changed SlotEqu.a->Slots.a.
; <SM29> 11/2/92 kc Make change to prevent unwanted branch island (to data).
; <SM28> 10/27/92 fau Rolled in a Horror patch for TestForFPU that also works for
; 040's without and FPU. This is to support Tempest. Added the
; necessary changes to the programming of the YMCA for Tempest.
; <SM27> 10/25/92 HY Add code in jumpintoRom to turn on & grey LC/LC II screen early.
; <SM26> 10/20/92 fau Stopped using "MMC/YMCAexists" and replaced by either comparing
; against DecoderKind or by using PSCexists. Also, changed
; YMCAAddr/MMCAddr to use DecoderAddr.
; <SM25> 10/18/92 CCH Added support for PDM and conditionalized support for Smurf.
; <SM24> 10/12/92 RB For the 1 Meg LC930 ROM, exclude all code not related to the LC
; hardware.
; <SM23> 9/30/92 fau Added support for Cyclone EVT4. This involved new DRAM/ROM
; speed values and a modification to GetHardwareInfo so that it
; looks at the CycloneEVT4 product info.
; <SM22> 9/25/92 RB Excluded some functions such as INITVias from executing while
; booting from RAM. Added a ROM base for the LC 2. Hacked
; GetCPUIDReg to return Cyclone when ROMinRAM testing.
; <SM21> 8/27/92 CCH Removed some now obsolete conditionals for Smurf card.
; <SM20> 8/25/92 chp Fix assembler warning.
; <SM19> 8/24/92 PN Take out CycloneboxEVT1
; <SM18> 8/20/92 CCH Don't initialize Orwell when running on a Cub Card.
; <SM17> 8/17/92 CCH Extended Universal support to 96-bits, added GetExtHardwareInfo
; routine to provide dynamic checking for feature existence.
; <SM16> 08-11-92 jmp Fixed a problem in the GetCPUIDReg routine where the CACR was
; being trashed; this caused 030 machines to die before BootBeep.
; <SM15> 8/9/92 CCH Removed uneeded conditionals and temporarily return a CPU ID
; for RISC cards.
; <SM14> 7/28/92 fau Corrected the Cyclone MMC_DRAMspeed0/1 to point to a 25MHz CPU
; with 60ns DRAM, instead of 25MHz with 80ns DRAM.
; <SM13> 7/21/92 kc Fix duplicate lable.
; <SM12> 7/13/92 CCH Added conditionalized support for Cub Card.
; <SM11> 6/30/92 kc Fix bug introduced with last checkin (trashing d0).
; <SM10> 6/26/92 GS (RBM) Add call to CudaInit to perform a SyncAck cycle prior to
; any transaction with Cuda. This will disable all asynchronous
; message sources within Cuda and will prevent any collisions from
; occuring in the low level io primitive routines prior to
; installation of the Cuda manager.
; <SM9> 6/21/92 RB • Added a temporary check for EVT1 Cyclone in InitVIAs and
; CheckBases so that we don't have to support two builds for the
; next few weeks.
; <SM8> 6/9/92 kc Roll in Horror change from UniversalPatch.a,14.
; <H16> 5/28/92 BG Fixed a bug in GetHardwareInfoPatch. If you have the -Ext- bit
; set in your CPU ID register, -GetVIAInputs- gets called to read
; VIA1 to see what machine you really are. However, A1 was a bad
; register to save the A6 return value in. A3 is better.
; <SM7> 5/25/92 RB Changed a couple of branch longs to short branches since the
; code is not in patches anymore. Some VIA1 init code got lost in
; pass <SM5>, so it has been restored now.
; <SM6> 5/22/92 RB Removed an ENDIF
; <SM5> 5/22/92 RB Forgot to add comments in the previous checkin. Added tables for
; Cyclone, checks for MMC which identify a a Cyclone machine (for
; now I think) and got rid of the IF forCyclone changes previously
; made. Added VIA init stuff for Cyclone, its decoder table and
; video info.
; <SM4> 5/22/92 RB Making changes for Cyclone
; <SM3> 5/17/92 kc Roll the Horror changes. Comments follow: • From
; UniversalPatch.a:
; <H14> 4/20/92 NJV Adding changes needed to support Patch ROMs
; <H13> 4/13/92 JC Remove dynamic speed determination from Sonora setup code.
; <H12> 2/20/92 JC Fix register trashing bug in test for Sonic code and remove
; temporary branch around Sonic test.
; <H11> 2/14/92 JC Clean up Sonora Memory controller initialization, dynamically
; determine clock speed, and add TestforSonic code.
; <T13> 4/26/91 ag Relocate the stack pointer after we jump into rom, otherwise a
; berr will cause ram to be written to!
; <T12> 4/22/91 ag added patch to reinitialize berr handler after jump into rom.
; removed aux wait state initialization in jaws.
; <T11> 2/16/91 BG Changed the Orwell initialization to understand 33MHz.
; <T10> 1/15/91 HJR Added new code in memoryCtrlInitPatch for Jaws initialization.
; <T7> 11/7/90 BG Made changes for new rev. of Orwell (2) permanent.
; <T4> 10/30/90 BG Added changes for new rev. of Orwell (2).
; <T3> 10/25/90 CCH Added support for ReAnimator when forRomulator equate is set.
; • From Univeral.a:
; <H9> 12/16/91 HJR Export some symbols and introduce Decoder Niagra and Product
; Dartanian into product list. Temporarily use the same routine
; for CheckForJaws and CheckForNiagra until Niagra has some
; distinguishing characteristic.
; <H8> 12/12/91 SWC Don't touch RvMonP in InitVIAs if we're running on an MSC since
; that register offset is used for, among other things, RAM
; sizing.
; <T9> 12/7/90 BG (actually JMA) Added support for dual SCSI buses used on
; Eclipse. Also - merged CheckForRPU with new CheckForSCSI96
; routine into new patch.
; <T6> 1/18/90 SWC Fixed an alignment problem where code grew by 2 bytes in
; TestForIOP. Also changed FMCInit to FMCRPUInit since we don't
; know if we have parity yet.
; <T6> 10/29/90 CCH Fixed forRomulator conditional statement.
; <T5> 10/25/90 CCH Added support for ReAnimator when forRomulator equate is set.
; <SM2> 4/7/92 JSM Roll-in revision <63> from Reality:
; <63> 3/24/92 JSM Nuke more code names: boxAuroraCX25 is boxMacIIci, boxF19 is
; boxMacIIfx.
; <62> 1/27/92 KC Move Allign 16 macro above rombase table.
; <61> 1/23/92 RB Changed the order of items in the Decoder lookup table. Changed
; the Eclipse VIA info record.
; <60> 1/20/92 RB Backed out to the revision <58>. For some reason making the code
; that sets up a bus error handler a procedure would freeze the
; machine upon startup. Very weird because the problem is not
; obvious. If only that 040 emulator worked...added an ALIGN for
; the 040 emulator. Got rid of the padForOverpatch at the end of
; the file.
; <59> 1/15/92 RB Revisited terror changes. Added a forRomulator change. Made code
; that sets up the buss error handler a subroutine since it gets
; called twice.
; <58> 12/29/91 RB Added Terror changes and rolled in patches to support Quadras
; and PowerBooks.
; <57> 12/21/91 RB Need to change boxTim and boxEclipse to the release names.
; <56> 10/17/91 JSM Get rid of all the stupid conditionals.
; <55> 10/1/91 JSM Dont use onMvMac conditional, Modern Victorian never existed.
; <54> 10/1/91 JSM Dont use eclipseDebug.
; <53> 9/10/91 JSM Cleanup header.
; <52> 1/18/91 KIP <JDR> Add Sound8BitMono bit to the Universal ROM flags for TIM,
; since it has built-in sound input.
; <51> 10/24/90 JJ Rex V8: Roll in changes from Rex V8 splitoffs.
; <50> 10/22/90 JJ Rex V8: Change VISAChipBit to V8ChipBit.
; <49> 9/25/90 SAM Changed boxElsie/boxErickson to boxMacLC/boxMacIIsi
; <48> 9/13/90 MSH Converted Waimea to TIM. This involved the boxflag, names, and
; clock/PRAM implementation.
; <47> 9/1/90 BG Updated Eclipse-related information to reflect the EVT1 boards.
; <46> 8/15/90 BG Fixed an error in the conditionals at the bottom of JumpIntoROM.
; <45> 8/14/90 BG Added an address map definition for SONIC on Eclipse. This uses
; the previously unused Address23 in the I/O map tables.
; <44> 8/14/90 BG Saved the original bus error vector for the NUB on Eclipse.
; <43> 8/2/90 CCH Temporarily cleared hwCfgFPU on Eclipse.
; <42> 6/25/90 BG Modified the EclipseNuBus information to correctly reflect the
; fact that slot E is not available on the current prototypes.
; <41> 6/18/90 CCH Added eclipse-specific changes, and removed occurences of the
; onEclipse equate.
; <40> 6/11/90 GA Correct VideoInfo 24-bit base address for Erickson. Somehow, it
; seemed to get lost from <39>.
; <39> 6/7/90 HJR Changes the 24 Bit Address in MDU and Erickson to 32 Bit
; Addresses since the video stuff pulls that address and Quickdraw
; requires it to be a 32 bit address.
; <38> 5/25/90 MSH JAWS check was all wrong. Changed logical 24 Bit address in MDU
; and Erickson to reflect actual 24 Bit address.
; <37> 5/17/90 JJ Change address of diagnostic ROM for VISA decoder.
; <36> 5/14/90 MSH Moved built in video to logical slot E and the PDS connector to
; slot B.
; <35> 5/2/90 CV Updating nuBus slot info to reflect change in the video slot for
; Erickson.
; <34> 5/1/90 DAF Updating Erickson VideoInfo for Built-in Video in Slot $E.
; <33> 4/24/90 DAF Reordered Elsie VideoInfo records to match new RBVPrimaryInit.a
; <32> 4/21/90 GMR Reversed order of entries in RamInfo tables.
; <31> 4/20/90 JJ Removed support for VISA 1 from Elsie RAM Info Table.
; <30> 4/20/90 JJ Change initial sound volume value for Elsie and Erickson from 2
; to 6.
; <29> 4/12/90 MSH Fixed the Waimea clock/PRAM info in tables.
; <28> 4/11/90 JJ Change sound volume initilization value from 1 to 2 on Erickson
; and Elsie to avoid BURNIN rack problem.
; <27> 4/11/90 JJ Change VIA1Init table for Erickson and Elsie to set DDRA bits
; 0:2 to be outputs.
; <26> 4/4/90 JJ Modified Elsie Video Information Tables.
; <25> 4/4/90 MSH Added Waimea to the tables. Made the pad bytes at the bottom
; conditional for overpatching only.
; <24> 4/2/90 djw Fixup universal NuBusInfo tables for Elsie, Erickson, and
; Eclipse.
; <23> 3/26/90 CCH Added sound input to external feature flags for Erickson, Elsie,
; and Eclipse.
; <22> 3/23/90 JJ Made RAMInforElsie tables conditional on hasVISA2.
; <21> 3/22/90 JJ Fixed bug in JumpIntoROM. Now relocates pointers to Decoder
; Info and Product Info before "jmp @intoROM(d3.l)".
; <20> 3/9/90 JJ Changed RAMInfoElsie table to conform to VISA2 memory
; configurations.
; <19> 2/23/90 BG Moved reference to Orwell to before the Glue DecoderTable entry
; since Eclipse/Orwell will pass the GLUE test, but a MacII will
; fail the Orwell test.
; <18> 2/21/90 BG Fixed off-by-one error in Orwell setup code.
; <17> 2/20/90 CCH Set Eclipse smallest bank size to 4 meg.
; <16> 2/16/90 BG Modified TestForFPU to check if we're running on an 040 before
; the SFC check. Running on an 040 implies you have an FPU. The
; SFC check will fail on an 040 because it does not support
; coprocessor communications. Also modified OrwellDecoderTable to
; include the possibility of a DiagROM, etc.
; <15> 2/13/90 JJ Stupid mistake in Version <14>.
; <14> 2/13/90 JJ Added VISA chip indicator to External Feature flags in VISA
; decoder table and Elsie information table.
; <13> 2/9/90 BG Adding Eclipse-specific hardware information. Also added a
; *CheckForOrwell* routine to determine if we're dealing with
; Orwell decoder. Also added Orwell initialization code in
; JumpIntoROM.
; <12> 2/7/90 OR Add CheckForVISADecoder routine and all information tables for
; Elsie.
; <11> 2/7/90 CV Rearranged order of CheckFeatures & CheckOptionals to use d1,
; not d3 in TestForFPU. d3 contains warmstart value. Sorry!
; <10> 2/4/90 GMR Fixed VIA init table for Erickson, so it properly initializes
; the vACR reg for Egret.
; <9> 2/4/90 CV Removed isUniversal conditional on TestForFPU. Caused HcMac &
; Macpp to fail.
; <8> 2/3/90 CV Added TestForFPU to check for an optional FPU.
; <7> 2/1/90 CV Adding a table for via1 initialization for Erickson. Erickson
; was using the IIci table, but EGRET requires different
; initialization. On Erickson, three lines are used to communicate
; with EGRET and five lines are unconnected.
; <6> 1/25/90 GMR Renamed the ADB/Clock types so they don't conflict with assembly
; conditionals (like iopADB).
; <5> 1/15/90 GMR Added ADB and Clock/Pram bits to External Features longword, to
; help support Erickson/Elsie which use the Egret chip.
; <4> 1/11/90 CCH Added include of “HardwarePrivateEqu.a”.
; <3> 1/8/90 CV Adding table information to allow recognition of Erickson as a
; new CPU. Changing the via1 id value for AuroraSE25 to 0. The
; value it was set to ($16) conflicts with Erickson's cpu id.
; <2> 1/2/90 SWC Changed CheckForOSSFMC to work with TI as well as NCR parts.
; <2.5> 11/15/89 GMR Added TestForRPU to check for the optional RPU chip on OSS/FMC,
; changed the decoder table for OSS/FMC and the InfoF19 table.
; Fixed bug in TestForIOP when setting increment mode.
; <2.4> 8/22/89 BBM UGLY HACK. made a quick patch to the bbu table just to get emacs
; working.
; <2.3> 7/25/89 CCH Changed JumpIntoROM to preserve the value in the VBR if
; forRomulator is true.
; <2.2> 7/16/89 GGD Changed the product info for the former Aurora 16 to be the same
; as Aurora 25, but without the PGC option. Added a flag to the
; ExtValid flags of Aurora 25 to indicate that it has the PGC
; option installed. Renamed AuroraCX25 to be MacIIciPGC and
; AuroraCX16 to be MacIIci.
; <2.0> 6/30/89 GGD Initialized the new DefaultRSRCs field in the ProductInfo
; record. Added some padding to allow for overpatching. Added
; NuBus Slot Info.
; <•2.1> 6/30/89 GGD Changed resource combos from 0,1 to 1,2
; <2.1> 6/30/89 GGD Changed the DefaultRSRCs from {0,1} to {1,2}
; <2.0> 6/30/89 GGD Initialized the new DefaultRSRCs field in the ProductInfo record.
; Added some padding to allow for overpatching. Added NuBus Slot Info.
; <1.9> 6/12/89 djw Added slot video pram addr to video table
; <1.8> 6/11/89 GGD Added Video, Ram Bank, hwCfgFlags, and ROM85 info to tables.
; Updated GetHwInfo to also return the hwCfgFlags. Updated VIA2
; initialization values.
; <1.7> 6/10/89 GGD Added info for new aurora boxes. GetHwInfo now clears the beok
; bit when done.
; <1.6> 5/29/89 GGD Fixed wrong register bug in FMC initialization. Removed the Test
; in Ram checks.
; <1.5> 5/20/89 GGD Updated to use new IOP equates from HardwareEqu, deleted local
; IOP equates.
; <1.4> 5/16/89 rwh separated out Mac II Via 2 info to set MMU control bit as an
; output.
; <1.3> 5/15/89 GGD Changed RBV BufB initialization to disable Par.Test~ so that
; correct parity will be generated.
; <1.2> 5/10/89 CCH Added a test that will make the vFC3 bit an output when running
; in RAM.
; <1.1> 5/1/89 GGD Fixed conditionals in CheckForGLUE so that NuMac will work
; again.
; <1.0> 4/30/89 GGD Adding to EASE for the first time. Support for Universal ROM.
;__________________________________________________________________________________________________
print off
LOAD 'StandardEqu.d'
INCLUDE 'HardwarePrivateEqu.a'
INCLUDE 'UniversalEqu.a'
INCLUDE 'PowerPrivEqu.a'
INCLUDE 'STEqu.a'
INCLUDE 'Slots.a'
INCLUDE 'DepVideoEqu.a' ; <58> rb
INCLUDE 'EgretEqu.a' ; <SM38>
print on
print nomdir
machine mc68030
mc68881 ; needed for TestForFPU <SM28>
Universal proc export
import CPUIDProductLookup,ProductLookup,DecoderLookup
import BaseOfRom, CudaInit
import SendEgretCmd ; <SM38>
EXPORT CheckForUnknown
export GetHardwareInfo
export GetExtHardwareInfo ; <SM17>
export JumpIntoROM
export InitVIAs
EXPORT CheckNextMap,MapFound ;<SM31> ; <H2>
IF hasCPUIDRegister THEN ; ; <SM24> rb <SM36> rb
EXPORT GetCPUIDReg ;<SM49>
ENDIF
;_______________________________________________________________________
;
; Routine: JumpIntoROM
; Inputs: A6 - return address
;
; Outputs: A0 - Pointer to DecoderInfo record for this machine
; A1 - Pointer to ProductInfo record for this machine
; D0 - Flags indicating which base addresses are valid
; D1 - Flags indicating which external features are valid
; D2 - Bits 31..16, hwCfgFlags info (possibly unknown)
; D2 - Bits 15..8, BoxFlag info (possibly unknown)
; D2 - Bits 7..0, Address Decoder Kind (zero if unknown)
;
; Destroys: A2,A3,SP,D3,D4,D5
; Called by: BSR6
;
; Function: Locates the System ROM, which we are executing out of,
; but which may be mapped down to zero (overlay mode).
; We will jump into the ROM at its normal base address,
; and then initialize the VIAs to disable overlay.
;
;_______________________________________________________________________
with DecoderInfo,ProductInfo,DecoderKinds
JumpIntoROM
move.l #aStack,sp ; set stack pointer value
movea.l a6,a4 ; save the return address
; Setup VBR to point to a temporary Bus Error handler, because we need to use
; Bus Errors to destinguish the address decoders on the 68020/030 machines.
lea GotBusError,a0 ; get the handler address
move.l a0,d0 ; value to search for
@loop cmp.l -(a0),d0 ; check for a match
beq.s @found ; use the entry if it matches
tst.l (a0) ; check for end of list
bne.s @loop ; if not, keep searching
lea BusErrVct,a0 ; set it up in RAM
move.l d0,(a0) ; assume ram based, insert entry
@found subq.w #BusErrVct,a0 ; make it the bus error vector
IF forRomulator THEN ; <T5>
TestInRAM a3 ; are we in RAM?
beq.s @notInRAM ;
movec vbr,d5 ; save contents of vbr <T5>
movec vbr,a3 ; get vbr address in a1
move.l BusErrVct(a3),d2 ; save original (read: NUB) buserr vect
movec d2,USP ; ... in an out-of-the-way place
move.l BusErrVct(a0),BusErrVct(a3) ; copy old vector to new table
@notInRAM
ELSE ; <T6>
movec.l a0,vbr ; install the vector table
ENDIF
@TryAgain moveq.l #0,d2 ; figure it out from scratch
bsr6 GetHardwareInfo ; figure out what we are running on
btst.l #ROMExists,d0 ; see if we have a ROM
beq.s @TryAgain ; if not, we're screwed, but try again anyway
; Now figure out what the new base of ROM should be,
IF forRomulator THEN ; <T5>
TestInRam A2 ; running in RAM? <T5>
bne.s intoROM ; yep, skip this.. <T5>
endif
biglea BaseOfRom,a2 ; where we currently start
move.l ROMAddr(a0),d3 ; where we want to start (from savepatch) <3> <cv>
sub.l a2,d3 ; offset we need to add to relocate <3> <cv>
adda.l d3,a0 ; relocate decoder info pointer <3> <cv>
adda.l d3,a1 ; relocate product info pointer <3> <cv>
; if not forRamRom then ; ••• need to make this a runtime check •••
adda.l d3,a4 ; relocate the return address
jmp intoROM(d3.l) ; relocate our program counter
; endif
intoROM ; now we are in ROM
; Setup VBR to point to a temporary Bus Error handler, because we need to use
; Bus Errors to destinguish the address decoders on the 68020/030 machines.
adda.l d3,sp ; relocate the stack to rom addresses <T13>
lea GotBusError,a0 ; get the handler address <T12>
move.l a0,d0 ; value to search for <T12>
@loop cmp.l -(a0),d0 ; check for a match <T12>
beq.s @found ; use the entry if it matches <T12>
tst.l (a0) ; check for end of list <T12>
bne.s @loop ; if not, keep searching <T12>
lea BusErrVct,a0 ; set it up in RAM <T12>
move.l d0,(a0) ; assume ram based, insert entry <T12>
@found subq.w #BusErrVct,a0 ; make it the bus error vector <T12>
IF forRomulator THEN ; <T12>
TestInRAM a3 ; are we in RAM? <T12>
beq.s @notInRAM ; <T12>
movec vbr,d5 ; save contents of vbr <T12>
movec vbr,a3 ; get vbr address in a1 <T12>
move.l BusErrVct(a3),d2 ; save original (read: NUB) buserr vect <T12>
movec d2,USP ; ... in an out-of-the-way place <T12>
move.l BusErrVct(a0),BusErrVct(a3) ; copy old vector to new table <T12>
@notInRAM
ELSE ; <T12>
movec.l a0,vbr ; install the vector table <T12>
ENDIF
@TryAgain moveq.l #0,d2 ; figure it out from scratch <T12>
bsr6 GetHardwareInfo ; figure out what we are running on <T12>
btst.l #ROMExists,d0 ; see if we have a ROM <T12>
beq.s @TryAgain ; if not, we're screwed, but try again anyway <T12>
IF NOT ROMinRAM THEN ; <SM22> rb
bsr6 InitVIAs ; initialize the VIAs (turns off vOverlay) <T12>
ENDIF ; <SM22> rb
; Here, after running GetHardwareInfo we have: <SM10>{rbm}<2>
; <SM10>{rbm}<2>
; a0 - Pointer to table of base addresses <SM10>{rbm}<2>
; a1 - Pointer to ProductInfo record for this machine <SM10>{rbm}<2>
; d0 - Flags indicating which base addresses are valid <SM10>{rbm}<2>
; d1 - Flags indicating which external features are valid <SM10>{rbm}<2>
; d2 - Bits 31..16, hwCfgFlags info (possibly unknown) <SM10>{rbm}<2>
; d2 - Bits 15..8, BoxFlag info (possibly unknown) <SM10>{rbm}<2>
; d2 - Bits 7..0, Address Decoder Kind (zero if unknown) <SM10>{rbm}<2>
; <SM10>{rbm}<2>
; CudaInit implies a SyncAck cycle which synchronizes Cuda to the system and disables <SM10>{rbm}<2>
; all asynchronous messages sources (Auto Poll, RTC, Power Messages, Unknown). No further <SM10>{rbm}<2>
; individual disabling of asynchronous message sources is required. (R. Montagne 5/25/92) <SM10>{rbm}<2>
; <SM10>{rbm}<2>
move.l d0,d3 ; save a copy of d0 <SM11>
move.l #EgretFWMask,d0 ; mask for Egret Firmware <SM10>{rbm}<2>
and.l d1,d0 ; isolate the field <SM10>{rbm}<2>
sub.l #Egret8,d0 ; see if we have Egret FW <SM10>{rbm}<2>
beq.w @DoEgretInit ; do Egret 8 FW INIT, LC/si <SM10>{rbm}<2> <SM38>
sub.l #Egret8,d0 ; see if we have Caboose FW <SM10>{rbm}<2>
beq.s @CudaDone ; just exit Quadra900 <SM10>{rbm}<2> <SM39> PN
sub.l #Egret8,d0 ; see if we have Cuda FW <SM10>{rbm}<2>
bne.s @CudaDone ; if not, just exit <SM10>{rbm}<2>
IF NOT ROMinRAM THEN ; <SM22> rb
BigBSR6 CudaInit ;Setup Cuda Sysnc Ack with System <SM10>{rbm}<2>
bra.s @CudaDone ; <SM38>
ENDIF ; <SM22> rb
@DoEgretInit ; <SM38>
movea.l DecoderInfo.VIA1Addr(a0),a1 ; get VIA 1 base address <SM38>
move.w #4000,d0 ; <SM38>
@wait
eieioSTP
tst.b (a1) ; sync to hardware for 1.2µS per access <SM38>
dbra d0,@wait ; Egret must see idle before command, it's busy <SM38>
; doing ADB reset for 3mSec so delay in idle state <SM38>
eieioSTP
move.l #(NopCmd<<16)|pseudoPkt,d0 ; <SM38>
moveq #0,d2 ; no bytes to send <SM38>
bsr6 SendEgretCmd ; send the command to disable async. messages <SM38>
moveq.l #0,d2 ; figure it out from scratch <SM38>
bsr6 GetHardwareInfo ; restore all the registers we trashed <SM38>
move.l d0,d3 ; by calling SendEgretCmd <SM38>
@CudaDone
move.l d3,d0 ; restore d0 <SM11>
IF forSTP601 THEN
jmp (a4) ; Orwell,djmec already inited...return
ENDIF
IF hasOSS THEN ; <SM36> rb
btst.l #OSSExists,d0 ; see if we have an OSS
beq.s @noOSS ; if not, don't need to init it
movea.l OSSAddr(a0),a3 ; get the OSS base address
move.b #OSSRomInit,OSSRomCntl(a3) ;overlay off, 2 ROM wait states
@noOSS
ENDIF ; <SM36> rb
IF hasFMC THEN ; <SM36> rb
btst.l #FMCExists,d0 ; see if we have a FMC
beq.s @noFMC ; if not, don't need to init it
movea.l FMCAddr(a0),a3 ; get the FMC base address
move.w #FMCRPUInit,d3 ; initial value for config register <T6>
moveq.l #16-1,d4 ; loop counter to load 16 bits
@FMCload move.b d3,FMCConfig(a3) ; load in a bit <1.6>
lsr.w #1,d3 ; put next bit into position
dbra d4,@FMCload ; repeat till all bits loaded
move.b d3,FMCLatch(a3) ; latch the config data
@noFMC
ENDIF ; <SM36> rb
IF hasSonora THEN ; begin hasSonora <H11>.Start <SM36> rb
move.l ExtValid(a1),d3 ; get External Flags
btst.l #SonoraExistsBit,d3 ; see if we have an Sonora ASIC
beq @noSonora ; IF we have a Sonora THEN
lea CPUIDReg,A2 ;get value in CPU ID Reg <H13>.Start
move.l (a2),d3
and.l #$0000ff00,d3 ; only look at CPU ID reg Design Center Value
movea.l RBVAddr(a0),a2 ; get base of RBV/VIA2 Registers
move.b #0,SonoraVRAMSize(a2) ;force VRAM to 256k for now
move.b #$40,SonoraRAMSize(a2) ;force to 25 Mhz PDS slot speed <SM4> rb
move.b #3,SonoraSpeedReg(a2) ;Set up for 33Mhz timing
cmpi.w #cpuIDHiEnd,d3 ; check if we are a high end box
bge.s @noSonora ; branch if high end box
lea CPUIDReg,A2 ;get value in CPU ID Reg <H27><SM31>
move.l (a2),d3 ; <H27><SM31>
and.w #cpuIDFieldMask,d3 ; d3 = ID field of CPU ID Register <H26><SM31>
cmpi.w #Vail33IDField,d3 ; is it a 33 MHz Vail ?? <H26><SM31>
beq.s @noSonora ; yep, don't change the timing <H26><SM31>
movea.l RBVAddr(a0),a2 ; get base of RBV/VIA2 Registers <H29><SM31>
move.b #2,SonoraSpeedReg(a2) ;Set up for 25Mhz or less timing <H13>.End
@noSonora ; end hasSonora <H11>.End
ENDIF ; <SM36> rb
IF hasOrwell THEN ; <SM36> rb
; Eclipse/040 Memory Controller INIT
cmp.b #OrwellDecoder,DecoderKind(a1) ; see if we have an Orwell Mem. Cntrlr
bne.s @noOrwell ; NOPE ... we don't need to init. it
cmp.b #boxRiscQuadra700,ProductKind(a1) ; see if we're on a RISC Quadra <SM54>
beq.s @noOrwell ; don't reset orwell then <SM54>
cmp.b #boxRiscQuadra900,ProductKind(a1) ; see if we're on a RISC Quadra <SM54>
beq.s @noOrwell ; don't reset orwell then <SM54>
cmp.b #boxRiscQuadra950,ProductKind(a1) ; see if we're on a RISC Quadra <SM54>
beq.s @noOrwell ; don't reset orwell then
; Set up various Orwell configuration registers to useable values.
movea.l DecoderAddr(a0),a3 ; get base address of Orwell regs <SM17>
move.l #ORWELL_INIT25,d4 ; get Orwell 25MHz initialization value <T11>
moveq.l #OrCfgRegSize-3,d3 ; (34-3 = 34-1-2) -1 for DBRA, <T4><T7>
; -2 because 32-bit max constant size <T4>
movea.l VIA2Addr(a0),a2 ; get base of VIA2 to check for 33 MHz <T11>
bclr #v2Speed,VDirB(a2) ; make sure the 25/33MHz direction=input<T11>
btst #v2Speed,VBufB(a2) ; are we running at 25 MHz or 33 MHz? <T11>
beq.s @25MHz ; IF CPU_Speed == 33MHz THEN <T11>
move.l #ORWELL_INIT33,d4 ; get Orwell 33MHz init. value <T11>
@25MHz ; ENDIF <T11>
; Note - the above configuration constants are ONLY accurate for non-parity <T11>
; operation. <T11>
lea OrBankBCfgAddr(a3),a2; get address of config regs. <T11>
@OrwellINIT move.l d4,(a2)+ ; send that bit out there
lsr.l #1,d4 ; get the next bit in position
dbra d3,@OrwellINIT ; repeat til all bits loaded
; now move in the last two bits that didnt fit in the original 32-bit constant<T4><T7>
moveq #ORINITWaitWr1,d4 ; get initial value of optional write wait state<T4><T7>
move.l d4,(a2)+ ; ... and send that bit out <T4><T7>
; RAS precharge (the last bit) is done separately below because it too relies <T11>
; on the clock speed the processor is running at. <T11>
; Now hit the associated latch registers to actually store the values
move.l d3,OrLoadBanks(a3) ; initialize DRAM bank starting addrs
move.l d3,OrLoadSpeeds(a3) ; initialize Clock/DRAM/ROM speeds
move.l d3,OrLoadRefresh(a3); initialize refresh rate
move.l d3,OrLoadParity(a3) ; initialize parity on/off + type
move.l d3,OrLoadMode(a3) ; initialize page mode (on/off) <T4><T7>
move.l d3,OrLoadWaitStates(a3); initialize optional wait states <T4><T7>
; RAS Precharge timing is different depending on 25/33 MHz.
move.l OrClkSpeedAddr(a3),d4; now that clock speed is set, get it <T11>
btst #0,d4 ; only LSBit is valid from each reg addr<T11>
beq.s @use33MHzvalue ; IF Clock_Speed == 25MHz THEN <T11>
moveq #ORINITRAS25,d4 ; get value of 25 MHz RAS precharge <T4><T7><T11>
bra.s @initRAS ; and get on with it <T11>
@use33MHzvalue ; ELSE <T11>
moveq #ORINITRAS33,d4 ; get value of 33 MHz RAS precharge <T4><T7><T11>
@initRAS ; ENDIF
move.l d4,(a2) ; ... and finish init of config reg <T4><T7>
move.l d3,OrLoadPrecharge(a3); initialize RAS precharge (on/off) <T4><T7>
@noOrwell
ENDIF ; <SM36> rb
IF hasJaws THEN ; <SM36> rb
btst.l #JAWSExists,d0 ; see if we have a JAWS <T10> HJR
beq.s @noJAWS ; if not, don't need to init it
movea.l JAWSAddr(a0),a2 ; get base address of Jaws regs
movea.l a2,a3 ; copy the register
adda.l #JAWSGetCPUClock,a3 ; get address of CPU clock register
move.b (a3),d3 ; read CPU clock register
andi.b #1,d3 ; clear the top bits
move.b d3,JAWSRAMWaitS(a2) ; set ram wait states according to the speed register
@noJAWS
ENDIF ; <SM36> rb
IF hasYMCA THEN ; <SM36> rb
cmp.b #YMCADecoder,DecoderKind(a1) ; Do we have a YMCA <SM26> fau start
bne @noYMCA ; Not a YMCA <SM26> fau end
Move.l DecoderAddr(a0),A2 ; Get Base of YMCA. <SM23> <SM26> <SM34>
Cmp.b #BoxQuadra840AV,ProductKind(a1) ; Are we running on a Cyclone40 <SM34> <LW2><SM55>
Beq.s @DoCyclone40 ; if so, go program it <SM34>
Cmp.b #BoxCyclone33,ProductKind(a1) ; Are we running on a Cyclone33 <SM34>
Beq.s @DoCyclone33 ; if so, go program it <SM34>
Cmp.b #BoxTempest33,ProductKind(a1) ; Are we running on a Tempest25 <SM34> <LW2>
Beq.s @DoTempest33 ; if so, go program it <SM34>
Cmp.b #BoxCentris660AV,ProductKind(a1) ; Are we running on a Tempest25 <SM34> <LW2><SM55>
Beq @DoTempest25 ; if so, go program it <SM34>
Bra @noYMCA ; Not a Cyclone Type Machine
@DoCyclone40
Move.l #0,YMCA_DRAMspeed0(A2) ; Set DRAM speed to 60ns with a 40MHz CPU <SM34><LW7>
Move.l #-1,YMCA_DRAMspeed1(A2) ; <SM34><LW7
Move.l #0,YMCA_CPUspeed0(A2) ; Set CPU Speed to 40 MHz <SM34><LW7
Move.l #-1,YMCA_CPUspeed1(A2)
Move.l #0,YMCA_ROMspeed0(A2) ; Set ROM speed to 127ns (7 cycles). <SM34><LW7>
Move.l #0,YMCA_ROMspeed1(A2) ; <SM34><LW7>
Move.l #-1,YMCA_ROMspeed2(A2) ; <SM34>
; Program MUNI if it exists
bsr6 GetExtHardwareInfo ; Get the bits for extended features 32-63 <SM34>
beq @NoYMCA ; No MUNI here <SM34>
Move.l #$1c,MUNIBase+MUNI_Control ; Set MUNI for 33MHz. <SM34>
Bra.s @noYMCA ; Skip over Tempest programming <SM34>
@DoCyclone33
@DoTempest33 ; <SM34>
Move.l #-1,YMCA_DRAMspeed0(A2) ; Set DRAM speed to 60ns with a 33MHz CPU <SM23>
Move.l #0,YMCA_DRAMspeed1(A2) ; <SM23>
Move.l #-1,YMCA_CPUspeed0(A2) ; Set CPU Speed to 33 MHz <SM23>
Move.l #0,YMCA_CPUspeed1(A2)
Move.l #-1,YMCA_ROMspeed0(A2) ; Set ROM speed to 125 (6 cycles). <SM23> <LW7>
Move.l #-1,YMCA_ROMspeed1(A2) ; <SM23> <LW7>
Move.l #0,YMCA_ROMspeed2(A2) ; <SM23> <LW7>
; Program MUNI if it exists
bsr6 GetExtHardwareInfo ; Get the bits for extended features 32-63 <SM32>
beq.s @NoYMCA ; No MUNI here <SM32>
Move.l #$18,MUNIBase+MUNI_Control ; Set MUNI for 33MHz. <SM23>
Bra.s @NoYMCA ; Skip over Tempest programming <SM26>
@DoTempest25
Move.l #0,YMCA_DRAMspeed0(A2) ; Set DRAM speed to 60ns with a 25MHz CPU <SM26><LW7>
Move.l #0,YMCA_DRAMspeed1(A2) ; <SM26><LW7>
Move.l #0,YMCA_CPUspeed0(A2) ; Set CPU Speed to 25 MHz <SM26><LW7>
Move.l #0,YMCA_CPUspeed1(A2)
Move.l #0,YMCA_ROMspeed0(A2) ; Set ROM speed to 140ns (5 cycles). <SM26><LW7
Move.l #-1,YMCA_ROMspeed1(A2) ; <SM26>
Move.l #0,YMCA_ROMspeed2(A2) ; <SM26>
; Program MUNI if it exists
bsr6 GetExtHardwareInfo ; Get the bits for extended features 32-63 <SM32>
btst.l #MUNIExists-32,d0 ; Normalize MUNIExists since it's in 32-63 <SM32>
beq.s @NoYMCA ; No MUNI here <SM32>
Move.l #$14,MUNIBase+MUNI_Control ; Set MUNI for 25MHz. <SM32>
@NoYMCA
ENDIF ; <SM36> rb
IF hasVisaDecoder THEN ; <SM36> rb
cmp.b #VISADecoder,DecoderKind(a1) ; do we have a VISA <SM27>
bne.s @noVISA ; if not don't do anything <SM27>
; <SM27>
; VISA machines need there screens greyed out earlier than primary init time <SM27>
; to avoid garbage being left over on the screen from a previous reboot <SM27>
move.l VDACAddr(a0),a2 ; get base address of Color Table chip <SM27>
move.l a2,a3 ; save base address in a3 <SM27>
clr.b V8DACwCntlReg(a2) ; clears the overlay enable bit and puts ariel in slave mode <SM27>
; ; to insure all outputs are off while CLUT is being filled <SM27>
adda #V8DACwDataReg,a2 ; point to data register <SM27>
clr.b V8DACwAddReg-V8DACwDataReg(a2) ; start at the beginning of CLUT, 4-bit mode <SM27>
move.b #$7F,d3 ; get a 50% value <SM27>
move #$FF,d4 ; get count <SM27>
@Repeat move.b d3,(a2) ; put red (CLUT autoincrements destination address) <SM27>
move.b d3,(a2) ; put green <SM27>
move.b d3,(a2) ; put blue <SM27>
dbra d4,@Repeat ; <SM27>
ori.b #$08,V8DACwCntlReg(a3) ; turn video on by putting machine in master mode <SM27>
@noVISA
ENDIF ; <SM36> rb
IF hasDJMEMC THEN ; <SM36> rb
; djMEMC Configuration Register initialization <H18> thru next <H18>
; (Done here so that it isn't done multiple times in SizeMemPatch) <SM30> begin
move.l ExtValid(a1),d3 ; get External Flags
btst.l #djMEMCChipBit,d3 ; see if we have a djMEMC
beq @nodjMEMC ; IF we have a djMEM THEN
cmp.b #boxRiscCentris650,ProductKind(a1) ; see if we're on a RISC Wombat Centris650 <SM54>
beq @nodjMEMC ; don't reset djMEMC then <SM54>
cmp.b #boxRiscQuadra800,ProductKind(a1) ; see if we're on a RISC Wombat Quadra800 <SM54>
beq @nodjMEMC ; don't reset djMEMC then <SM54>
cmp.b #boxRiscCentris610,ProductKind(a1) ; see if we're on a RISC Wombat Centris610 <SM54>
beq @nodjMEMC ; don't reset djMEMC then <SM54>
; Set up djMEMC+BIOS Configuration Registers:
; -------------------------------------------
;
; Get machine type + CPU speed information from VIA1
;
; Useful VIA1 PortA bits to read: PA6, PA4, PA2, PA1 ($56)
;
; PA6 = Lego (1), or Frigidaire (0) plastics for Wombat
; PA4, PA2 = CPU Speed. 0=20MHz, 1=25MHz, 2=33MHz, 3=40MHz
; PA1 = WLCD (0) or NOT! [Reserved] (1)
;
; Retrieve CPU Speed information from VIA1 Port A
move.l VIA1Addr(a0),a2 ; get VIA1 address to get machine/cpu_speed info
moveq #%00101000,d3 ; force VIA1 VDirA to have the correct directions
eieioSTP
move.b d3,VDirA(a2) ; ... so we can read the CPU ID extension info
moveq #%00010100,d3 ; get VBufA, bits PA4, PA2 (dont need PA6, PA1)
eieioSTP
and.b VBufA(a2),d3 ; get plastics_type/cpu_speed information
@hasValue lsr.b #2,d3 ; shift over to get PA2 in LSBit
btst #4-2,d3 ; test PA4. remember it's been shifted from bit pos. 4->2
beq.s @PA4IsZero ; if its already zero, don't do anything
bset #1,d3 ; otherwise move it down to correct place for indexing
@PA4IsZero andi.b #$03,d3 ; make sure ONLY bottom 2 bits are set
moveq.l #-1,d4 ; initial offset into @MachineTbl-one_entry <H35> thru next <H35> <SM57>
@nextEntry addq.l #1,d4 ; get next entry
tst.w (@MachineTbl,d4.w*2) ; if entry is zero, you've hit EndOfTable
beq.s @unknownMachine ; deal with unknown machine
moveq.l #%01010110,d0 ; CPU ID mask value for VIA
eieioSTP
and.b VBufA(a2),d0 ; get CPU ID value
cmp.b (@MachineTbl+1,d4.w*2),d0 ; is it this machine?
bne.s @nextEntry ; no, try again
LEA @djConfigTable,A3 ; assume original table
move.b (@MachineTbl,d4.w*2),d0 ; check whether we're an Original or a Bumped machine
beq.s @doIt ; 0=Original, use @djConfigTable.
@unknownMachine ; SpeedBump or Unknown machine, assume SpeedBump
LEA @BumpConfigTable,A3 ; use SpeedBump configuration table
@doIt
LEA MEMCAddr,A2 ; Get djMEMC base
move.w (a3,d3.w*2),d0 ; use CPU speed as index into table for config value <H35> <SM57>
MOVE.L D0,MEMCconfig(A2) ; set up configuration register
move.w (@djRefreshTable,d3.w*2),d0 ; also use CPU speed as index into refresh period table
MOVE.L D0,MEMCRefresh(A2) ; set up refresh period
LEA BIOSAddr,A2 ; get base of BIOS
MOVE.L BIOS_Config(A2),d0 ; get Config register value
andi.b #$F7,d0 ; drop old D0{0:0} value
or.b (@BIOS_Config,d3.w),d0 ; only change bit 0 of this register
MOVE.L d0,BIOS_Config(A2) ; and write it out (only bottom 8-bits "stick")
move.w (@BIOS_Timeout,d3.w*2),d0 ; get watchdog timer timeout count-down value
MOVE.L d0,BIOS_Timeout(A2) ; and and write this out
bra.s @nodjMEMC ; finished with memory controller initialization
; djMEMC Configuration register initialization values for different CPU speeds
;
; [ See the djMEMC ERS for a full description of the Configuration Register ]
align 4 ; longword align
; djMEMC Configuration Register initialization values
@djConfigTable
@dj20Config dc.w %0000000100000001 ; fastwr=1, ROMspeed=1
@dj25Config dc.w %0000000000011010 ; drpchg=1, drpw=1, ROMspeed=2
@dj33Config dc.w %0000000010100011 ; mhz33=1, cyc23ta=1, ROMspeed=3 <H24>
@dj40Config dc.w %0000001011110100 ; dwcpw=1, mhz33=1, drcpw=1, cyc2ta=1, drpchg=1, ROMspeed=4 <H22>
; DRAM refresh cycle times assuming a 15.6µs refresh period <H25>
; (Refresh = (MHz * 15.6 ) - 27). Fractional parts are rounded DOWN <H25>
@djRefreshTable
@dj20Refresh dc.w 285 ; (20MHz * 15.6µs) - 27 <H25>
@dj25Refresh dc.w 363 ; (25MHz * 15.6µs) - 27 <H25>
@dj33Refresh dc.w 487 ; (33MHz * 15.6µs) - 27 <H25>
@dj40Refresh dc.w 597 ; (40MHz * 15.6µs) - 27 <H25>
; BIOS Configuration Register initialization values <h28>
@BIOS_Config
@BIOS_Config20 dc.b %00000001 ; BCLK_25 = 1 <H28>
@BIOS_Config25 dc.b %00000001 ; BCLK_25 = 1 <H28>
@BIOS_Config33 dc.b 0 ; BCLK_25 = 0 <H28>
@BIOS_Config40 dc.b 0 ; BCLK_25 = 0 <H28>
; BIOS watchdog timer timeout count-down value <H28>
@BIOS_Timeout
@BIOS_Timeout20 dc.w $0280 ; <H28>
@BIOS_Timeout25 dc.w $01E0 ; <H28>
@BIOS_Timeout33 dc.w $00D5 ; <H28>
@BIOS_Timeout40 dc.w 0 ; <H28>
; Table for determining whether or not to use "SpeedBump"ed Config values <H35> thru next <H35> <SM57>
@DJ_ORIG EQU 0
@DJ_BUMP EQU 1
@MachineTbl ; Type CPU VIA ID
dc.b @DJ_ORIG,%00010010 ; 33MHz Frigidaire package (Quadra 800) <SM60>
dc.b @DJ_BUMP,%00010110 ; 40MHz Frigidaire package (unreleased) <SM60>
dc.b @DJ_ORIG,%01000000 ; 20MHz WLCD (Centris 610)
dc.b @DJ_BUMP,%01000100 ; 25MHz WLCD (Quadra 610)
dc.b @DJ_BUMP,%01010000 ; 33MHz WLCD (unreleased) <SM60>
dc.b @DJ_ORIG,%01000110 ; 25MHz Lego package (Centris 650)
dc.b @DJ_BUMP,%01010010 ; 33MHz Lego package (Quadra 650)
dc.b @DJ_BUMP,%01010110 ; 40MHz Lego package (Quadra 650 SpeedBump, unreleased) <SM60>
dc.b @DJ_ORIG,0 ; if here, this is EndOfTable
; VIA CPUID of 0 is a reserved (unused) machine.
; Configuration register values for SpeedBumped machines (by clock speed)
@BumpConfigTable
@bump20Config dc.w %0000000100000001 ; fastwr=1, ROMspeed=1
@bump25Config dc.w %0000000000011010 ; drpchg=1, drpw=1, ROMspeed=2
@bump33Config dc.w %0000000011111011 ; mhz33=1, drcpw=1, cyc2ta=1, drpchg=1 drpw=1, ROMspeed=4 <H24>
@bump40Config dc.w %0000001011111100 ; dwcpw=1, mhz33=1, drcpw=1, cyc2ta=1, drpchg=1, drpw=1, ROMspeed=5 <H22>
; <H35> <SM57>
@nodjMEMC ; <SM30> end
ENDIF ; <SM36> rb
; =======================================================================================================
; Pratt Configuration Register initialization <K4> thru next <K4>
; (Done here so that it isn't done multiple times in SizeMemPatch)
IF hasPratt THEN
IF isUniversal THEN ;
cmp.b #PrattDecoder,DecoderKind(a1) ; do we have a Pratt <SM27>
BNE.S @NotPratt ; IF we have a Pratt THEN
ENDIF ; { isUniversal }
MOVE.B #(1<<WhitneySWIMReset)|\; Clear the reset line to swim
(1<<WhitneyEnetReset)\ ; Clear the reset line to Sonic
,WhitneyPwrCtl ;
@NotPratt
ENDIF ; { hasPratt } <K4>
; =======================================================================================================
IF forRomulator THEN ; <T3>
TestInRAM a3 ; are we in RAM?
beq.s @notInRAM2 ;
movea.l d5,a3 ; get location of original VBR <T3>
movec USP,d5 ; retrieve original buserr value <T3>
move.l d5,BusErrVct(a3) ; and restore it in the exception table <T3>
movec a3,vbr ; restore vbr <T3>
@notInRAM2
ENDIF ; { forRomulator } <T3>
jmp (a4) ; all inited, return
ALIGN 16 ; <60><62> rb, for the 040 emulator...
dc.l 0,0,0,0 ; end of list
dc.l (GotBusError-BaseOfRom)+$40A00000 ; base of Elsie II ROM <SM22> rb
dc.l (GotBusError-BaseOfRom)+$00A00000 ; base of Elsie ROM <51>
dc.l (GotBusError-BaseOfRom)+$40000000 ; alternate base of normal ROM <58> rb
dc.l (GotBusError-BaseOfRom)+$40800000 ; base of normal ROM
dc.l (GotBusError-BaseOfRom)+$00000000 ; base of overlay ROM
GotBusError btst.l #beok,d7 ; indicate that bus error occured
move.l a5,a7 ; restore stack
rts6 ; return
;_______________________________________________________________________
;
; Routine: InitVIAs
; Inputs: A0 - Pointer to table of base addresses
; A1 - Pointer to ProductInfo record for this machine
; D0 - Flags indicating which base addresses are valid
; D1 - Flags indicating which external features are valid
; D2 - Bits 15..8, BoxFlag info (possibly unknown)
; D2 - Bits 7..0, Address Decoder Kind (zero if unknown)
; A6 - return address
;
; Outputs: None
;
; Destroys: A2,A3,D3
; Called by: BSR6
;
; Function: Initializes the VIA1/VIA2/RBV direction, output and interrupt
; registers as well as general initialization of the VIAs.
;
;_______________________________________________________________________
with DecoderInfo,ProductInfo
InitVIAs
btst.l #VIA1Exists,d0 ; see if we have VIA1
beq @VIA1done ; if not, skip it
movea.l VIA1Addr(a0),a2 ; get VIA base address <SM5> rb
movea.l a1,a3 ; get product info ptr <SM5> rb
adda.l VIA1InitPtr(a3),a3 ; point to the init info <SM5> rb
btst.l #PSCExists,d0 ; is this a Cyclone ? <SM5> rb<SM4> rb, start <SM26>
beq.s @WombatVIAInit ; if not, check if we're a Wombat
;
; This change is valid only for the Cyclone VIA1 Info Table...
; The other machine tables will have to be updated to follow this initialization
; or there will be problems. The DirA, BufA, and DirB, BufB regs have been Inited
; in a different order than in previous ROMS... THIS MUST BE UPDATED!!!!
; gjs ????
;
eieioSTP
move.b (a3)+,vDirA(a2) ; init direction for port A <P9> gjs
eieioSTP
move.b (a3)+,vBufA(a2) ; init output port A <P9> gjs
eieioSTP
move.b (a3)+,vDirB(a2) ; init direction for port B <P9> gjs
eieioSTP
move.b (a3)+,vBufB(a2) ; init output port B <P9> gjs
eieioSTP
move.b (a3)+,vPCR(a2) ; init peripheral control reg <SM7> rb
eieioSTP
move.b (a3)+,vACR(a2) ; init auxiliary control reg <SM7> rb
eieioSTP
move.b #$7F,vIER(a2) ; Disable all VIA interrupts. <SM7> rb
eieioSTP
bra.s @VIA1done ; cool, keep going <SM5> rb
@WombatVIAInit ; <SM31>
IF hasDJMEMC THEN ; <SM36> rb
cmpi.b #djMEMCDecoder,d2 ; are we on a Wombat? <SM31><SM41>
bne.s @doOldVIAInit ; if not, initialize VIAs the old way <SM31><SM41>
eieioSTP
move.b (a3)+,vBufA(a2) ; init output port A <SM31>
eieioSTP
move.b (a3)+,vDirA(a2) ; init direction for port A <SM31>
eieioSTP
move.b #$1C,vACR(a2) ; enable shift-out on ACR <H25><SM31>
eieioSTP
move.b #0,vSR(a2) ; preset shift register with an ADB resetCmd <H25><SM31>
eieioSTP
move.b (a3)+,vBufB(a2) ; init output port B <SM31>
eieioSTP
move.b (a3)+,vDirB(a2) ; init direction for port B <SM31>
eieioSTP
move.b -2(a3),vBufB(a2) ; (re-)init output port B <H25><SM31>
eieioSTP
move.b (a3)+,vPCR(a2) ; init peripheral control reg <SM31>
eieioSTP
move.b (a3)+,vACR(a2) ; init auxiliary control reg <SM31>
eieioSTP
move.b #$7F,vIER(a2) ; Disable all VIA interrupts. <SM31>
eieioSTP
bra.s @VIA1done ; cool, keep going <SM31>
ENDIF ; <SM36> rb
@doOldVIAInit ; <SM4> rb, start
eieioSTP
move.b (a3)+,vBufA(a2) ; init output port A
eieioSTP
move.b (a3)+,vDirA(a2) ; init direction for port A
eieioSTP
move.b (a3)+,vBufB(a2) ; init output port B
eieioSTP
move.b (a3)+,vDirB(a2) ; init direction for port B
eieioSTP
move.b (a3)+,vPCR(a2) ; init peripheral control reg
eieioSTP
move.b (a3)+,vACR(a2) ; init auxiliary control reg
eieioSTP
move.b #$7F,vIER(a2) ; Disable all VIA interrupts.
eieioSTP
@VIA1done
btst.l #VIA2Exists,d0 ; see if we have VIA2
beq.s @VIA2done ; if not, skip it
movea.l VIA2Addr(a0),a2 ; get VIA2 base address <SM4> rb, start
movea.l a1,a3 ; get product info ptr
adda.l VIA2InitPtr(a3),a3 ; point to the init info
IF hasPSC THEN ; <SM36> rb
btst.l #PSCExists,D0 ; Make sure we're on a Cyclone. <SM26>
Beq.s @NonPSC ; Not? Then do conventional init. <SM26>
Move.b PSCVIA2SInt(A2), D3 ; get PortA (slots) current values
eieioSTP
Or.b (A3)+, D3 ; or in via2 init info values
eieioSTP
Move.b D3, PSCVIA2SInt(A2) ; save new values
eieioSTP
Move.b #$7F, PSCVIA2IER(A2) ; disable all VIA2 interrupts.
eieioSTP
Move.b #$40, PSCVIA2IFR(A2) ; clear sound frame int.
eieioSTP
Bra.s @VIA2done ; this takes care of Cyclones
@NonPSC ; <SM4> rb, end <SM26>
ENDIF ; <SM36> rb
eieioSTP
move.b vBufA(a2),d3 ; get current values
eieioSTP
or.b (a3)+,d3 ; or in the default values
eieioSTP
move.b d3,vBufA(a2) ; init output port A
eieioSTP
move.b (a3)+,vDirA(a2) ; init direction for port A
eieioSTP
move.b (a3)+,vBufB(a2) ; init output port B
eieioSTP
move.b (a3)+,vDirB(a2) ; init direction for port B
eieioSTP
move.b (a3)+,vPCR(a2) ; init peripheral control reg
eieioSTP
move.b (a3)+,vACR(a2) ; init auxiliary control reg
eieioSTP
move.b #$7F,vIER(a2) ; Disable all VIA2 interrupts.
eieioSTP
; Simulate the Macintosh VBL interrupt by using timer 1 to output a square wave on PB7 of VIA #2.
; On NuMac, this output is tied to the CA1 pin of VIA #1 which is used for VBL on a Mac.
; Timer 1 causes the PB7 output to invert each time the counter reaches 0.
; There is an additional 2 tick delay while the VIA resets the counter. We get 783360 ticks/sec
; (Which is C16M/20). Mac VBL interrupt is 60.15 (C16M/(704*370)). The VIA responds on the
; negative edges only. So:
; timer 1 = (ticks/rate)/2 - 2
; = ((C16M/20)/(C16M/(704*370)))/2 - 2
; Note: VIA2 PB7 is not tied to anything on Waimea. JAWS generates this clock for us.
@T2Count equ ((704*370)/20)/2-2 ; VIA ticks per half-cycle
eieioSTP
move.b #@T2Count**$FF,vT1C(a2) ; Load low byte into counter/latch.
eieioSTP
move.b #@T2Count>>8,vT1CH(a2) ; Load high byte and off we go!
eieioSTP
@VIA2done
btst.l #RBVExists,d0 ; see if we have an RBV
beq.s @RBVdone ; if not, skip it
movea.l RBVAddr(a0),a2 ; get RBV base address
eieioSTP
move.b #$7F,RvIER(a2) ; disable all interrupts
eieioSTP
move.b #$8F,RvDataB(a2) ; initialize data reg. B <1.3>
eieioSTP
BTST #MSCChipBit,D1 ; are we using an MSC variant? <H8>
BEQ.S @NoMSC ; -> no, continue on <H29><SM31>
; This is the point where we check to see if an external FPU is attached to <H31>
; the system. In the case of Escher, the onboard FPU will power up disabled, <H31>
; but we want to enable it here if we don't detect anything else sitting on <H31>
; the coprocessor bus. <H31>
;
; The idea is to move VBR DOWN the difference between the F-Line and
; BusError, so that if you were to execute an F-Line instruction and
; couldn't handle it, you would end up fetching the address of the
; BusErrVector and going thru the BusErrVector. The BusErr handler
; expects A6 to contain the address of where it should return TO.
movec VBR,d3 ; retrieve VBR
sub.l #Line1111-BusErrVct,d3 ; temporarily move VBR down
movec d3,VBR ; shuffle VBR for F-Line test
moveq #1,d3 ; non-zero value in D3 for later comparison
move.l a7,a5 ; sp to restore if you dont have an FPU
move.l a6,a3 ; save return address
bset #beok,d7 ; set bus error expected flag
lea @noFPU,a6 ; where to come back to if you dont have an FPU
FNOP ; execute suspect command
clr.l d3 ; if you got here, you already have an FPU
@noFPU tst.b d3 ;
beq.s @ignore ; already using an FPU so ignore internal
bclr #MSCEnableFPU,RvDataB(a2);enable onboard FPU
@ignore
movec VBR,d3 ; return VBR to it's old value
add.l #Line1111-BusErrVct,d3
movec d3,VBR ; ... so everyone is happy
bclr #beok,d7 ; release bus error expected flag
move.l a3,a6 ; restore return address <H31>
MOVE.B #$7F,RvSEnb(A2) ; disable all slot interrupts <H29><SM31>
eieioSTP
RTS6 ; <H29><SM31>
@NoMSC ; <H29><SM31>
eieioSTP
move.b #1<<RvVIDOff,RvMonP(a2) ; turn off onboard video <SM31>
eieioSTP
move.b #$FF,RvSEnb(a2) ; set all slots to be interrupt enabled <SM31>
eieioSTP
@RBVdone
rts6
;_______________________________________________________________________
;
; Routine: GetHardwareInfo
; Inputs: D2 - Bits 15..8, BoxFlag info (only if decoder kind <> 0)
; D2 - Bits 7..0, Address Decoder Kind (zero if unknown)
; A6 - return address
; A7, D7, VBR - setup for bus error handler
;
; Outputs: A0 - Pointer to DecoderInfo record for this machine
; A1 - Pointer to ProductInfo record for this machine
; D0 - Flags indicating which base addresses are valid 0-31
; D1 - Flags indicating which external features are valid 0-31
; D2 - Bits 31..16, hwCfgFlags info (possibly unknown)
; D2 - Bits 15..8, BoxFlag info (possibly unknown)
; D2 - Bits 7..0, Address Decoder Kind (zero if unknown)
;
; Destroys: A2, A5
; Called by: BSR6
;
; Function: Determines the hardware configuration of this machine.
;
; NOTE: The 'beok' bit in D7 will always be cleared when this routine exits.
;
;_______________________________________________________________________
EXPORT FoundMatch ; <SM31>
with DecoderKinds,DecoderInfo,ProductInfo
GetHardwareInfo
; Use the new CPUID register scheme if supported on this CPU. (from GetHardwareInfoPatch)
bset.l #beok,d7 ; allow bus errors
movea.l a7,a5 ; mark the stack for bus error handler
IF hasCPUIDRegister THEN ; ; <SM24> rb <SM36> rb
movea.l a6,a1 ; save return address for GetHardwareInfo in a1
bsr6 GetCPUIDReg ; get CPUID register if it exists
movea.l a1,a6 ; restore return address for GetHardwareInfo
beq.s @foundCPUIDReg ; IF we don't have a CPUID register THEN
bra HasNoCPUIDReg ; ->CONTINUE in GetHardwareInfo using old recognition method <SM7> rb
@foundCPUIDReg ; ENDIF
biglea CPUIDProductLookup-4,a2 ; get address of CPUID product lookup table
@MatchLoop ; LOOP (through product info entries to match CPU ID)
addq.w #4,a2 ; bump to next entry
move.l (a2),d1 ; see if end of list reached
beq UnknownCPU ; if we got to the end, we're severely hosed.
lea (a2,d1.l),a1 ; a1 := pointer to ProductInfo record
cmp.w CPUIDValue(a1),d0 ; see if product and CPU ID match
bne.s @MatchLoop ; if not, keep searching
btst #11,d0 ; is the complete CPU ID in the CPUID register?
beq Matched ; -> yes, we've got it
cmpi.b #PrattDecoder,\ ; IF Decoder is a Pratt THEN <K4>
DecoderKind(a1) ; Found Match <K4>
beq Matched ; { For Now just handle one case } <K4>
movea.l DecoderInfoPtr(a1),a0 ; get the pointer to this machine's decoder table
adda.l a1,a0
move.l DefaultBases(a0),d0 ; and get the default bases flags
IF hasYMCA THEN ; <SM36> rb
cmp.b #YMCADecoder,DecoderKind(a1) ; Do we have a YMCA controller <SM26> fau start
bne.s @GetVia ; No, go do the regular kind <SM26> fau end
Move.l DecoderAddr(a0),A1 ; Base of YMCA. <SM23> <SM26>
Move.l YMCA_CPUID0(A1),D0 ; Bit 0 of CPU ID. <SM23>
Move.l YMCA_CPUID1(A1),D1 ; Bit 1 of CPU ID. <SM23>
Rol.l #1,D0 ; Move to bit 0. <SM23>
And.b #1,D0 ; Only care about bit 0. <SM23>
Rol.l #2,D1 ; Move to bit 1. <SM23>
And.b #2,D1 ; Only care about bit 1. <SM23>
Or.b D1,D0 ; Complete ID. <SM23>
Move.l YMCA_CPUID2(A1),D1 ; Bit 2 of CPU ID. <SM23>
Rol.l #3,D1 ; Move to bit 1. <SM23>
And.b #4,D1 ; Only care about bit 1. <SM23>
Or.b D1,D0 ; Complete ID. <SM23>
Move.l YMCA_CPUID3(A1),D1 ; Bit 3 of CPU ID. <SM23>
Rol.l #4,D1 ; Move to bit 1. <SM23>
And.b #8,D1 ; Only care about bit 1. <SM23>
Or.b D1,D0 ; Complete ID. <SM23>
move.l (a2),d1 ; Get the relative offset to the ProductInfo record
lea (a2,d1.l),a1 ; and make it absolute
Cmp.b YMCAIdMatch(A1),D0 ; Do they match? <SM23>
Beq.s Matched ; Yes? Then let's get outta here. <P2>
Move.w CPUIDValue(a1),d0 ; Ack!!! We blew away D0 and it's needed in the MatchLoop loop, so
; we go and restore it. We are out of registers here.
Bra.s @MatchLoop ; No? Then try next product. <P2>
ENDIF ; hasYMCA <SM36> rb
@GetVia ; <SM4> rb, end
movea.l a6,a3 ; save return address for GetHardwareInfo in a1 <H16>
bsr6 GetVIAInputs ; read all of the VIA input lines into D1
movea.l a3,a6 ; restore return address for GetHardwareInfo <H16>
move.l (a2),d0 ; get the relative offset to the ProductInfo record
lea (a2,d0.l),a1 ; and make it absolute
and.l VIAIdMask(a1),d1 ; mask the VIA inputs
cmp.l VIAIdMatch(a1),d1 ; see if they match
beq.s Matched ; if so, you're done. else ... <H17><SM31>
movea.l a2,a3 ; save your place in the table in A3 <H17><SM31>
movea.l a6,a1 ; save return address for GetHardwareInfo in A1 <H17><SM31>
BSR6 GetCPUIDReg ; get CPU ID register value (again) <H17><SM31>
movea.l a1,a6 ; restore return address <H17><SM31>
movea.l a3,a2 ; restore our place in the table <H17><SM31>
bra.s @MatchLoop ; go look for another candidate to check <H17><SM31>
Matched ; END
bra.s FoundMatch ; yea!!! <SM7> rb
UnknownCPU bra.s UnknownCPU ; Ack!
ENDIF ; hasCPUIDRegister <SM24> rb <SM36> rb
HasNoCPUIDReg ; fall through to @MatchLoop
tst.b d2 ; check address decoder kind
beq.s FindDecoder ; if unknown decoder, search for it.
; The ProductKind and DecoderKind are setup in D2, find the matching ProductInfo record.
biglea ProductLookup-4,a0 ; point before the first product to check for
@MatchLoop addq.w #4,a0 ; point to next product to check for
move.l (a0),d0 ; see if end of list reached
beq.s FindDecoder ; if end, look start over, looking for decoder first
lea (a0,d0.l),a1 ; a1 := pointer to ProductInfo record
cmp.w ProductKind(a1),d2 ; see if product and decoder match
bne.s @MatchLoop ; if not, keep searching
FoundMatch
movea.l DecoderInfoPtr(a1),a0 ; get offset to DecoderInfo record
adda.l a1,a0 ; make it absolute
move.l BasesValid(a1),d0 ; get the base address valid flags
beq.s CheckBases ; we don't know for sure, so sniff around
bra CheckOptionals ; check for optional features (FPU) <8>
FindDecoder
move.l a6,d0 ; save return address in D0 for now
biglea DecoderLookup,a1 ; point to first table entry
CheckNextMap
movea.l a1,a0 ; get address of table entry
adda.l (a1)+,a0 ; a0 := pointer to DecoderInfo
movea.l CheckForProc(a0),a2 ; get offset to proc to check for this decoder
jmp (a0,a2.l) ; check for a this decoder
MapFound movea.l d0,a2 ; now save return address in A2
move.l DefaultBases(a0),d0 ; d0 := default bases valid flags
; an address decoder was found, now get all of the VIA inputs, to check for
; a match when multiple products share an address decoder.
bsr6 GetVIAInputs ; read all of the VIA input lines
movea.l a2,a6 ; restore the return address to A6
; The VIA inputs have been read into D1, now look for a matching product.
move.b AddrMap(a0),d2 ; get the address map to search for
biglea ProductLookup,a0 ; point before the first product to check for
@MatchLoop move.l (a0)+,d0 ; see if end of list reached
beq.s FindDecoder ; something is very wrong, and we don't have a clue
lea -4(a0,d0.l),a1 ; a1 := pointer to ProductInfo record
cmp.b DecoderKind(a1),d2 ; see if address decoders match
bne.s @MatchLoop ; if not, keep searching
move.l d1,d0 ; get the VIA inputs
and.l VIAIdMask(a1),d0 ; mask them
cmp.l VIAIdMatch(a1),d0 ; see if they match
bne.s @MatchLoop ; if not, try the next product
bra.s FoundMatch ; if found, return the info
CheckBases
move.l DefaultBases(a0),d0 ; get the default base flags
movea.l a6,a0 ; save return address
btst.l #RBVExists,d0 ; see if RBV might be allowed
beq.s @RBVDone ; if not, don't test for one
movea.l DecoderInfoPtr(a1),a2 ; get offset to decoder info
movea.l RBVAddr(a1,a2.l),a2
lea RvIER(a2),a2 ; base address of RBV VIER register
bsr6 TestForRvIER ; see if RBV exists
beq.s @RBVDone ; if found, has RBV and VDAC
bclr.l #RBVExists,d0 ; no RBV, clear the bit
bclr.l #VDACExists,d0 ; if no RBV, then assume no VDAC either
@RBVDone
bclr.l #VIA2Exists,d0 ; see if VIA2 might be allowed
beq.s @VIA2Done ; if not, don't test for one
movea.l DecoderInfoPtr(a1),a2 ; get offset to decoder info
movea.l VIA2Addr(a1,a2.l),a2 ; get VIA2 base address
IF hasPSC THEN ; <SM36> rb
btst.l #PSCExists, D0 ; do we have PSC? <SM4> rb, start <SM26>
Beq.s @noPSC ; no, do horror style VIA2 init <SM26>
lea PSCVIA2IER(a2),a2 ; base address of PSC VIA2 VIER register
Bra.s @gotVIA2
@noPSC ; <SM26>
ENDIF ; <SM36> rb
lea VIER(a2),a2 ; base address of VIA2 VIER register
@gotVIA2 ; <SM4> rb, end
bsr6 TestForVIER ; see if VIA2 exists
bne.s @VIA2Done ; if not found, no VIA2
bset.l #VIA2Exists,d0 ; has VIA2, set the bit
@VIA2Done
IF hasIopSwim THEN ; <SM36> rb
bclr.l #SWIMIOPExists,d0 ; see if SWIMIOP might be allowed
beq.s @SWIMIOPDone ; if not, don't test for one
movea.l DecoderInfoPtr(a1),a2 ; get offset to decoder info
movea.l SWIMIOPAddr(a1,a2.l),a2
bsr6 TestForIOP ; see if SWIM IOP exists
bne.s @SWIMIOPDone ; if not found, has regular IWM
bclr.l #IWMExists,d0 ; no regular IWM, clear the bit
bset.l #SWIMIOPExists,d0 ; has SWIMIOP, set the bit
@SWIMIOPDone
ENDIF ; <SM36> rb
IF hasIopScc THEN ; <SM36> rb
bclr.l #SCCIOPExists,d0 ; see if SCCIOP might be allowed
beq.s @SCCIOPDone ; if not, don't test for one
movea.l DecoderInfoPtr(a1),a2 ; get offset to decoder info
movea.l SCCIOPAddr(a1,a2.l),a2
bsr6 TestForIOP ; see if SCC IOP exists
bne.s @SCCIOPDone ; if not found, has regular SCC
bset.l #SCCIOPExists,d0 ; has SCCIOP, set the bit
bclr.l #SCCrdExists,d0 ; no regular SCC, clear the bit
bclr.l #SCCwrExists,d0 ; no regular SCC, clear the bit
@SCCIOPDone
ENDIF ; <SM36> rb
bclr.l #SCSIDMAExists,d0 ; see if SCSIDMA might be allowed
beq.s @SCSIDMADone ; if not, don't test for one
movea.l DecoderInfoPtr(a1),a2 ; get offset to decoder info
movea.l SCSIDMAAddr(a1,a2.l),a2
bsr6 TestForSCSIDMA ; see if SCSI DMA exists
bne.s @SCSIDMADone ; if not found, has regular SCSI
bset.l #SCSIDMAExists,d0 ; has SCSI DMA, set the bit
bclr.l #SCSIExists,d0 ; no regular SCSI
bclr.l #SCSIDackExists,d0 ; no SCSI DACK either
bclr.l #SCSIHskExists,d0 ; no SCSI Hardware Handshake either
@SCSIDMADone
; <58> rb, from Terror SCSI96AndRPUPatch <T9>
IF hasSCSI96 THEN ; <SM36> rb
bclr.l #SCSI96_1Exists, d0 ; see if 1st SCSI96 chip might be allowed
beq.s @SCSI96Done ; if not, don't test for one
movea.l DecoderInfoPtr(a1), a2 ; get offset to decoder info
movea.l SCSI96Addr1(a1,a2.l), a2 ; a2 <- SCSI96 base address
bsr6 TestForSCSI96 ; see if SCSI96 exists
bne.s @SCSI96Done ; if not found then some other SCSI hw
bset.l #SCSI96_1Exists, d0 ; has 1st SCSI96, set exists bit
bclr.l #SCSIDMAExists,d0 ; no SCSI DMA
bclr.l #SCSIExists,d0 ; no regular SCSI (5380)
bclr.l #SCSIDackExists,d0 ; no SCSI DACK
bclr.l #SCSIHskExists,d0 ; no SCSI Hardware Handshake
; Maybe we'll get lucky and fish another...
bclr.l #SCSI96_2Exists, d0 ; see if 2nd SCSI96 chip might be allowed
beq.s @SCSI96Done ; if not, don't test for one
movea.l DecoderInfoPtr(a1), a2 ; get offset to decoder info
movea.l SCSI96Addr2(a1,a2.l), a2 ; a2 <- SCSI96 base address
bsr6 TestForSCSI96 ; see if SCSI96 exists
bne.s @SCSI96Done ; if not found then some other SCSI hw
bset.l #SCSI96_2Exists, d0 ; has 1st SCSI96, set exists bit
@SCSI96Done
ENDIF ; <SM36> rb
bclr.l #RPUExists,d0 ; see if RPU might be allowed
beq.s @RPUDone ; if not, don't test for one
movea.l DecoderInfoPtr(a1),a2 ; get offset to decoder info
movea.l RPUAddr(a1,a2.l),a2
bsr6 TestForRPU ; see if SCSI DMA exists
bne.s @RPUDone ; if not found, no parity chip
bset.l #RPUExists,d0 ; has SCSI DMA, set the bit
@RPUDone
movea.l a0,a6 ; restore return address
movea.l a1,a0 ; get product info pointer
adda.l DecoderInfoPtr(a0),a0 ; get decoder info pointer
CheckOptionals
move.l HwCfgWord(a1),d2 ; access hardware cfg flags <8>
btst.l #hwCbFPU+16,d2 ; should FPU be installed
beq.s FPUDone ; branch if it shouldn't be installed <SM28>
movea.l a6,a2 ; save return address
bra TestForFPU ; see if FPU installed
FPUReturn movea.l a2,a6 ; restore return address <SM28>
beq.s FPUDone ; branch if FPU found
bclr.l #hwCbFPU+16,d2 ; otherwise,clear FPU installed flag
FPUDone
bset.l #beok,d7 ; allow bus errors <H12><H11 begin>
movea.l a7,a5 ; mark the stack for bus error handler <H12>
bclr.l #SonicExists,d0 ; see if Sonic might be allowed
beq.s @SonicDone ; if not, don't test for one
move.l a1,d1 ; save a1 <H12>
move.l SonicAddr(a0),a1 ; get Sonic Base Address <H12>
movea.l a6,a2 ; save return address
bsr6 TestForSonic ; see if Sonic exists
movea.l a2,a6 ; restore return address
move.l d1,a1 ; restore a1 <H12>
bne.s @SonicDone ; if not found, no Sonic chip
bset.l #SonicExists,d0 ; has Sonic, set the bit <H11 end>
@SonicDone
bclr.l #PatchROMExists,d0 ; see if PatchRom might be allowed <H14>.start
beq.s @PatchROMDone ; if not, don't test for one
move.l a1,d1 ; save a1 <H12>
move.l PatchRomAddr(a0),a1 ; get PatchRom Base Address <H12>
movea.l a6,a2 ; save return address
bsr6 TestForPatchRom ; see if PatchRom exists
movea.l a2,a6 ; restore return address
move.l d1,a1 ; restore a1 <H12>
bne.s @PatchRomDone ; if not found, no PatchRom chip
bset.l #PatchRomExists,d0 ; has PatchRom, set the bit <H14>.end
@PatchROMDone
; External features checked after CheckOptionals so that d1 can be used as a scratch register
CheckFeatures ; <11>
move.l ExtValid(a1),d1 ; get the external features valid flags <11>
bne.s @allDone ; know features, check for optional features <11>
move.l DefExtFeatures(a0),d1 ; get the default external features flags <11>
@allDone
bclr.l #beok,d7 ; disallow bus errors <1.7/8>
rts6 ; all done <8>
;_______________________________________________________________________ <SM17>
;
; Routine: GetExtHardwareInfo
;
; Inputs: A0 - Pointer to DecoderInfo record for this machine
; A1 - Pointer to ProductInfo record for this machine
; D2 - Bits 15..8, BoxFlag info (only if decoder kind <> 0)
; D2 - Bits 7..0, Address Decoder Kind (zero if unknown)
; A6 - return address
; A7, D7, VBR - setup for bus error handler
;
; Outputs: A0 - Pointer to DecoderInfo record for this machine
; A1 - Pointer to ProductInfo record for this machine
; D0 - Flags indicating which base addresses are valid #32-63
; D1 - Flags indicating which external features are valid #32-63
; D2 - Bits 31..16, hwCfgFlags info (possibly unknown)
; D2 - Bits 15..8, BoxFlag info (possibly unknown)
; D2 - Bits 7..0, Address Decoder Kind (zero if unknown)
; D3 - Flags indicating which base addresses are valid #64-95
; D4 - Flags indicating which external features are valid #64-95
;
; Destroys: A2, A5
; Called by: BSR6
;
; Function: Returns extended hardware information about the machine.
;
; NOTE: The 'beok' bit in D7 will always be cleared when this routine exits.
;
;_______________________________________________________________________
GetExtHardwareInfo
bset.l #beok,d7 ; allow bus errors
movea.l a7,a5 ; mark the stack for bus error handler
move.l BasesValid1(a1),d0 ; get the base address valid flags for #32-63
bne.s CheckExtOptionals1 ; IF we don't know what bases are valid THEN
CheckExtBases1
move.l DefaultBases1(a0),d0 ; get the default base flags for #32-63
movea.l a6,a0 ; save return address
;---------------
; Call "TestFor…" routines here to verify devices for #32-63 <SM17>
;---------------
; begin <SM32> fau
; See if we have a Muni
btst.l #MuniExists-32,d0 ; see if MUNI might be allowed
beq.s @MuniDone ; if not, don't test for one
movea.l DecoderInfoPtr(a1),a2 ; get offset to decoder info
movea.l (MUNIAddr,a1,a2.l),a2 ; get MUNI's base addresses
bsr6 TestForMUNI ; and go test for it
beq.s @MUNIDone ; if found, has MUNI
bclr.l #MUNIExists-32,d0 ; no MUNI, clear the bit
@MUNIDone
; See if we have a BART <SM53>
btst.l #BartExists-32,d0 ; see if BART might be allowed
beq.s @BartDone ; if not, don't test for one
movea.l DecoderInfoPtr(a1),a2 ; get offset to decoder info
movea.l (BartAddr,a1,a2.l),a2 ; get BART's base addresses
bsr6 TestForBART ; and go test for it
beq.s @BartDone ; if found, has BART
bclr.l #BartExists-32,d0 ; no BART, clear the bit
@BartDone
; end <SM32> fau
movea.l a0,a6 ; restore return address
movea.l a1,a0 ; get product info pointer
adda.l DecoderInfoPtr(a0),a0 ; get decoder info pointer
CheckExtOptionals1
;---------------
; Check for optional hardware devices for #32-63 here <SM17>
;---------------
move.l BasesValid2(a1),d3 ; get the base address valid flags for #64-95
bne.s CheckExtOptionals2 ; IF we don't know what bases are valid THEN
CheckExtBases2
move.l DefaultBases2(a0),d3 ; get the default base flags for #32-63
movea.l a6,a0 ; save return address
;---------------
; Call "TestFor…" routines here to verify devices for #64-95 <SM17>
;---------------
movea.l a0,a6 ; restore return address
movea.l a1,a0 ; get product info pointer
adda.l DecoderInfoPtr(a0),a0 ; get decoder info pointer
CheckExtOptionals2
;---------------
; Check for optional hardware devices for #64-95 here <SM17>
;---------------
;----------------------------------------------------------------------------------------
; Check external features
;----------------------------------------------------------------------------------------
CheckExtFeatures ; <11>
move.l ExtValid1(a1),d1 ; get the external features valid flags <11>
bne.s @chkFeatures1 ; know features, check for optional features <11>
move.l DefExtFeatures1(a0),d1 ; get the default external features flags <11>
@chkFeatures1
;---------------
; Check for external features here for #32-63 <SM17>
;---------------
move.l ExtValid2(a1),d4 ; get the external features valid flags <11>
bne.s @chkFeatures2 ; know features, check for optional features <11>
move.l DefExtFeatures2(a0),d4 ; get the default external features flags <11>
@chkFeatures2
;---------------
; Check for external features here for #64-95 <SM17>
;---------------
@allDone
bclr.l #beok,d7 ; disallow bus errors <1.7/8>
rts6 ; all done <8>
IF hasGlue THEN ; <SM24> rb <SM36> rb
;_______________________________________________________________________
;
; Routine: CheckForGLUE
; Inputs: A0 - Pointer to DecoderInfo record for this decoder
; A1 - Pointer to next entry in DecoderLookup table
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: Jumps to MapFound if GLUE is detected
; Jumps to CheckNextMap if not a GLUE Decoder
;
; Destroys: D1, D2, A2, A6
; Called by: BSR6
;
; Function: Checks to see a Mac II GLUE chip address decoder is present.
; A unique property of the GLUE chip is that it has a smaller
; I/O space, which repeats sooner than the other decoders in
; its class. So we check for VIA1 in it's normal place, and
; at the location that it will only wrap around with a GLUE
; decoder. If it is found in both places, then we assume that
; it is the GLUE chip decoder.
;
;_______________________________________________________________________
EXPORT CheckForGLUE ; <SM36> rb
CheckForGLUE
movea.l VIA1Addr(a0),a2
lea vIER(a2),a2
move.l #$00020000,d2 ; GLUE chip wrap offset
bsr6 TestVIERWrap ; see if it is a VIA IER register
bne.w CheckNextMap ; if not, keep searching
bra.w MapFound ; it's a Mac II GLUE decoder
ENDIF ; <SM36> rb
IF hasMDU THEN ; <SM36> rb
;_______________________________________________________________________
;
; Routine: CheckForMDU
; Inputs: A0 - Pointer to DecoderInfo record for this decoder
; A1 - Pointer to next entry in DecoderLookup table
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: Jumps to MapFound if MDU is detected
; Jumps to CheckNextMap if not a MDU Decoder
;
; Destroys: D1, D2, A2, A6
; Called by: BSR6
;
; Function: Checks to see a MDU chip address decoder is present.
; We check to see that the VIA wraps at the correct place,
; and that it doesn't wrap earlier, where the GLUE chip would
; wrap. We also check to see if the RBV and VDAC can be accessed
; without a bus error, since the MDU generates the DSACK for them
; and they shouldn't bus error, even if they don't exist. An
; OSS decoder will bus error in MDUs RBV and VDAC address ranges.
;
;_______________________________________________________________________
EXPORT CheckForMDU ; <SM36> rb
CheckForMDU
movea.l VIA1Addr(a0),a2
lea vIER(a2),a2
move.l #$00040000,d2 ; MDU chip wrap offset
bsr6 TestVIERWrap ; see if it is a VIA IER register
bne.w CheckNextMap ; if not, keep searching
sub.l #$00020000,d2 ; MDU VIA does not wrap at $20000
bsr6 TestVIERWrap ; see if it is a VIA IER register
beq.w CheckNextMap ; if so, keep searching
lea CheckNextMap,a6 ; if bus errors, not an MDU
movea.l RBVAddr(a0),a2
eieioSTP
tst.b (a2) ; RBV should never bus error
movea.l VDACAddr(a0),a2
eieioSTP
tst.b (a2) ; VDAC should never bus error
eieioSTP
bra.w MapFound ; it's a MDU decoder
ENDIF ; <SM36> rb
IF hasOss OR hasFMC THEN ; <SM36> rb
;_______________________________________________________________________
;
; Routine: CheckForOSSFMC
; Inputs: A0 - Pointer to DecoderInfo record for this decoder
; A1 - Pointer to next entry in DecoderLookup table
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: Jumps to MapFound if OSS/FMC is detected
; Jumps to CheckNextMap if not a OSS/FMC Decoder
;
; Destroys: D1, D2, A2, A6
; Called by: BSR6
;
; Function: Checks to see a OSS/FMC address decoder is present.
; We check to see that the VIA wraps at the correct place,
; and that it doesn't wrap earlier, where the GLUE chip would
; wrap. We also check to see if an OSS mask register exists,
; by trying to load it with priorities 1..6 (don't use 7, since
; if may cause a NMI to be generated).
;
;_______________________________________________________________________
EXPORT CheckForOSSFMC ; <SM36> rb
CheckForOSSFMC
movea.l VIA1Addr(a0),a2
lea vIER(a2),a2
move.l #$00040000,d2 ; OSS chip wrap offset
bsr6 TestVIERWrap ; see if it is a VIA IER register
bne.w CheckNextMap ; if not, keep searching
sub.l #$00020000,d2 ; OSS VIA does not wrap at $20000
bsr6 TestVIERWrap ; see if it is a VIA IER register
beq.w CheckNextMap ; if so, keep searching
lea CheckNextMap,a6 ; if bus errors, not an OSS
movea.l OSSAddr(a0),a2
move.b OSSMskFirst(a2),d1 ; save the old contents
lsl.w #8,d1 ; make room for temp use of low byte
moveq.l #6,d2 ; loop counter / data pattern
@OssLoop move.b d2,OSSMskFirst(a2) ; store a value (don't allow NMI=7)
TST.L AllOnes ; put $FFFFFFFF on the bus to scramble it <2>
move.b OSSMskFirst(a2),d1 ; read it back
andi.b #$07,d1 ; expect low bits to change
cmp.b d1,d2 ; see if they did
dbne d2,@OssLoop ; loop through all patterns
@Done lsr.w #8,d1 ; get saved value
move.b d1,OSSMskFirst(a2) ; restore it
tst.w d2 ; see if all patterns compared
bpl.w CheckNextMap ; if not, it's not an OSS chip
bra.w MapFound ; otherwise it's an OSS decoder
AllOnes dc.l $FFFFFFFF ; <2>
ENDIF ; <SM24> rb
IF hasVISADecoder THEN ; <SM36> rb
;_______________________________________________________________________
;
; Routine: CheckForVISADecoder
; Inputs: A0 - Pointer to DecoderInfo record for this decoder
; A1 - Pointer to next entry in DecoderLookup table
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: Jumps to MapFound if VISA decoder is detected
; Jumps to CheckNextMap if not a VISA Decoder
;
; Destroys: D1, D2, A2, A6
; Called by: BSR6
;
; Function: Checks to see if a VISA address decoder is present.
; First, we check for a VIA IER at the correct address.
; If it is there, we check that it does not appear again
; at an offset of $00040000 in order to eliminate GLUE, MDU,
; and OSS, all of which wrap at this offset. We also check
; to see if the VISA (RBV) and VDAC can be accessed
; without a bus error, since the VISA generates the DSACK for them
; and they shouldn't bus error, even if they don't exist. An
; OSS decoder will bus error in VISAs RBV and VDAC address ranges.
;
;_______________________________________________________________________
EXPORT CheckForVISADecoder ; <SM36> rb
CheckForVISADecoder
movea.l VIA1Addr(a0),a2 ; look for a VIA IER
lea vIER(a2),a2
bsr6 TestForVIER
bne.w CheckNextMap ; not found means can't be a VISA
move.l #$00040000,d2 ; other decoders wrap at this offset
bsr6 TestVIERWrap
beq.w CheckNextMap ; if it wraps, it's not a VISA
lea CheckNextMap,a6 ; if bus errors, not an MDU
movea.l RBVAddr(a0),a2
eieioSTP
tst.b (a2) ; VISA should never bus error
movea.l VDACAddr(a0),a2
eieioSTP
tst.b (a2) ; VDAC should never bus error
eieioSTP
bra.w MapFound ; if not, it's a VISA decoder
ENDIF ; <SM36> rb
IF hasOrwell THEN ; <SM24> rb <SM36> rb
;_______________________________________________________________________
;
; Routine: CheckForOrwell <13>
; Inputs: A0 - Pointer to DecoderInfo record for this decoder <13>
; A1 - Pointer to next entry in DecoderLookup table <13>
; A5, A7, D7, VBR - setup for bus error handler <13>
;
; Outputs: Jumps to MapFound if Orwell is detected <13>
; Jumps to CheckNextMap if not an Orwell Decoder <13>
;
; Destroys: D2, A2 <13>
; Called by: BSR6 <13>
;
; Function: Checks to see an Orwell address decoder is present. We check to see<13>
; if we get a bus error when trying to access Orwell's I/O control <13>
; register I/O space. Orwell is the only decoder that doesn't bus <13>
; error in that part of I/O space. <13>
;
;_______________________________________________________________________
EXPORT CheckForOrwell ; <SM36> rb
CheckForOrwell
lea CheckNextMap,a6 ; return to decoder search if we bus error <19>
movea.l DecoderAddr(a0),a2 ; look for an Orwell <SM17>
move.l (a2),d2 ; Orwell won't bus error <13>
bra.w MapFound ; otherwise it is an Orwell decoder <13>
ENDIF ; <SM36> rb
IF hasJaws THEN ; <SM36> rb
;_______________________________________________________________________ <SM4> rb, start
;
; Routine: CheckForJAWS
; Inputs: A0 - Pointer to DecoderInfo record for this decoder
; A1 - Pointer to next entry in DecoderLookup table
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: Jumps to MapFound if JAWS is detected
; Jumps to CheckNextMap if not a JAWS Decoder
;
; Destroys: D1, D2, A2, A6
; Called by: BSR6
;
; Function: Checks to see a JAWS chip address decoder is present.
; By the time we get here we already know that the VIA does not
; wrap at $40000 or $20000, and that the RBV and VDAC addresses
; cause a bus error. Just to be safe though, we do some of the
; same VIA checks that were done before.
;
;_______________________________________________________________________
EXPORT CheckForJAWS ; <SM36> rb
CheckForJAWS
movea.l VIA1Addr(a0),a2 ; Look for VIA wrap a various places
lea vIER(a2),a2
move.l #$00100000,d2 ; JAWS does wrap at $100000 <8> HJR
bsr6 TestVIERWrap ; see if it is a VIA IER register <8> HJR
bne.w CheckNextMap ; if so, keep searching <8> HJR
lsr.l #1,d2 ; JAWS doesn't wrap at $80000 <8> HJR
bsr6 TestVIERWrap ; see if it is a VIA IER register <8> HJR
beq.w CheckNextMap ; if not, keep searching <8> HJR
lsr.l #1,d2 ; JAWS doesn't wrap at $40000 <8> HJR
bsr6 TestVIERWrap ; see if it is a VIA IER register <8> HJR
beq.w CheckNextMap ; if so, keep searching
lea CheckNextMap,a6 ; now try the JAWS registers
movea.l JAWSAddr(a0),a2
tst.b (a2) ; JAWS should never bus error
bra.w MapFound ; it's a JAWS decoder
ENDIF ; <SM36> rb
IF hasNiagra THEN ; <SM36> rb
;_______________________________________________________________________ <H17> thru next
; <H17>
; Routine: CheckForNiagra
; Inputs: A0 - Pointer to DecoderInfo record for this decoder
; A1 - Pointer to next entry in DecoderLookup table
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: Jumps to MapFound if Niagra is detected
; Jumps to CheckNextMap if not a Niagra Decoder
;
; Destroys: D1, D2, A2, A6
; Called by: BSR6
;
; Function: Checks to see a Niagra chip address decoder is present.
; By the time we get here we already know that the VIA does not
; wrap at $40000 or $20000, and that the RBV and VDAC addresses
; cause a bus error. Just to be safe though, we do some of the
; same VIA checks that were done before.
;
;_______________________________________________________________________
Export CheckForNiagra
CheckForNiagra
movea.l VIA1Addr(a0),a2 ; Look for VIA wrap a various places
lea vIER(a2),a2
move.l #$FF200000,d2 ; Niagra doesn't wrap at $50100000
bsr6 TestVIERWrap ; see if it is a VIA IER register
beq.w CheckNextMap ; if not, keep searching
move.l #$00080000,d2 ; Niagra doesn't wrap at $00080000
bsr6 TestVIERWrap ; see if it is a VIA IER register
beq.w CheckNextMap ; if not, keep searching
lsr.l #1,d2 ; Niagra doesn't wrap at $40000
bsr6 TestVIERWrap ; Niagra if it is a VIA IER register
beq.w CheckNextMap ; if so, keep searching
lea CheckNextMap,a6 ; now try the Niagra registers
movea.l JAWSAddr(a0),a2
tst.b (a2) ; Niagra should never bus error
bra.w MapFound ; it's a Niagra decoder
; <H17> <SM4> rb,end
ENDIF ; <SM24> rb
;_______________________________________________________________________
;
; Routine: CheckForUnknown
; Inputs: A0 - Pointer to DecoderInfo record for this decoder
; A1 - Pointer to next entry in DecoderLookup table
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: Jumps to MapFound always.
;
; Destroys: D1, D2, A2, A6
; Called by: BSR6
;
; Function: This is the last decoder on the list of decoders to search,
; so if we get here, we can't identify the address decoder.
; We return to MapFound to indicate that this unknown decoder
; exists, but if we get here, we are really dead, and can't
; figure out enough to even try to tell someone about it.
;
;_______________________________________________________________________
CheckForUnknown
bra.w MapFound
;_______________________________________________________________________
;
; Routine: TestForVIER, TestVIERWrap
; Inputs: A2 - Address of the VIER register to test
; D2 - offset of alternate address to check for (wrap around)
; Used by TestVIERWrap, set to zero for TestForVIER.
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if not a valid VIER register, or bus error.
; - 1 (beq) if valid VIER register found.
;
; Destroys: D1
; Called by: BSR6
;
; Function: Checks to see if the specified I/O register is a VIA IER
; (interrupt enable) register, by first setting all bits of
; the register, and then clearing each bit individually.
; Also checks to see if the same register also exists at an
; alternate address in I/O space, to detect specific address
; wrap around characteristics of some address decoders.
;
;_______________________________________________________________________
TestForVIER ; A2 := address of VIER register to test
moveq.l #0,d2 ; D2 := wrap offset to test
TestVIERWrap ; A2 := address of VIER register to test
eieioSTP
tst.b (a2,d2.l) ; make sure wrap address can be accessed
eieioSTP
move.b (a2),d1 ; save old VIER value
eieioSTP
rol.w #8,d1 ; save it in the next byte
st.b d1 ; test pattern := $FF
move.b d1,(a2) ; set all bits of VIER
eieioSTP
@loop neg.b d1 ; pattern of bit to clear
eieioSTP
move.b d1,(a2) ; clear the lowest order bit
add.b d1,d1 ; shift the test pattern
beq.s @exit ; exit when all bits shifted out
neg.b d1 ; convert to mask of bits that should be set
eieioSTP
cmp.b (a2,d2.l),d1 ; see if they are set at the wrap address
eieioSTP
bne.s @exit ; if not, exit
cmp.b (a2),d1 ; see if they are set at the standard address
eieioSTP
beq.s @loop ; if so, keep testing
@exit ror.w #8,d1 ; get saved VIER value
eieioSTP
move.b #$7F,(a2) ; prepare to restore (clear all bits)
eieioSTP
move.b d1,(a2) ; restore original VIER value
eieioSTP
lsr.w #8,d1 ; 0 if VIER found
rts6
;_______________________________________________________________________
;
; Routine: TestForRvIER
; Inputs: A2 - Address of the RvIER register to test
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if not a valid RvIER register, or bus error.
; - 1 (beq) if valid RvIER register found.
;
; Destroys: D1, D2
; Called by: BSR6
;
; Function: Checks to see if the specified I/O register is a RBV IER
; (interrupt enable) register, by first setting all bits of
; the register, and then clearing each bit individually.
; There are some reserved bits in the RvIER register, which
; are ignored by this test.
;
;_______________________________________________________________________
TestForRvIER ; A2 := address of RvIER register to test
move.b (a2),d1 ; save old RvIER value
rol.w #8,d1 ; save it in the next byte
st.b d1 ; test pattern := $FF
eieioSTP
move.b d1,(a2) ; set all bits of RvIER
@loop
neg.b d1 ; pattern of bit to clear
eieioSTP
move.b d1,(a2) ; clear the lowest order bit
add.b d1,d1 ; shift the test pattern
beq.s @exit ; exit when all bits shifted out
neg.b d1 ; convert to mask of bits that should be set
eieioSTP
move.b (a2),d2 ; get the RvIER value
eor.b d1,d2 ; compare them
andi.b #$9F,d2 ; ignore the reserved bits
beq.s @loop ; if match found, keep testing
@exit ror.w #8,d1 ; get saved RvIER value
eieioSTP
move.b #$7F,(a2) ; prepare to restore (clear all bits)
eieioSTP
move.b d1,(a2) ; restore original RvIER value
eieioSTP
lsr.w #8,d1 ; 0 if RvIER found
rts6
;_______________________________________________________________________
;
; Routine: TestForSCC
; Inputs: A2 - Base write address of the SCC to test for.
; D2 - offset to SCC read base address from write base
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if SCC not found, or bus error.
; - 1 (beq) if valid SCC found.
;
; Destroys: D1
; Called by: BSR6
;
; Function: Checks to see if the specified I/O registers point to an
; SCC. The read and write addresses may be specified separatly
; since some address decoders require this. An SCC is detected
; by writing a two byte signature to the time constant register
; and reading it back. The old value is saved and restored to
; make this test non-destructive. In order to meet SCC timing
; requirements on systems like the Mac Plus that do not provide
; a hardware holdoff, extra delays are introduced between SCC
; accesses.
;
;_______________________________________________________________________
TestForSCC ; A2 := address of SCCrd
; D2 := offset of SCCwr-SCCrd
eieioSTP
tst.b bCtl(a2,d2.l) ; reset register pointer to reg 0
ror.b #8,d1 ; kill some time, non-destructive
eieioSTP
move.b #13,bCtl(a2) ; point to register 13, time const high
ror.b #8,d1 ; kill some time, non-destructive
eieioSTP
move.b bCtl(a2,d2.l),d1 ; save old time const high byte
ror.b #8,d1 ; kill some time, non-destructive
eieioSTP
move.b #12,bCtl(a2) ; point to register 12, time const low
lsl.l #8,d1 ; make room for low byte, kill time
eieioSTP
move.b bCtl(a2,d2.l),d1 ; save old time const low byte
ror.b #8,d1 ; kill some time, non-destructive
eieioSTP
move.b #13,bCtl(a2) ; point to register 13, time const high
ror.b #8,d1 ; kill some time, non-destructive
eieioSTP
move.b #'G',bCtl(a2) ; load in signature high byte
ror.b #8,d1 ; kill some time, non-destructive
eieioSTP
move.b #12,bCtl(a2) ; point to register 12, time const low
ror.b #8,d1 ; kill some time, non-destructive
eieioSTP
move.b #'D',bCtl(a2) ; load in signature low byte
ror.b #8,d1 ; kill some time, non-destructive
eieioSTP
move.b #13,bCtl(a2) ; point to register 13, time const high
lsl.l #8,d1 ; make room for byte, kill time
eieioSTP
move.b bCtl(a2,d2.l),d1 ; read back signature high byte
ror.b #8,d1 ; kill some time, non-destructive
eieioSTP
move.b #12,bCtl(a2) ; point to register 12, time const low
lsl.l #8,d1 ; make room for byte, kill time
eieioSTP
move.b bCtl(a2,d2.l),d1 ; read back signature low byte
subi.w #'GD',d1 ; see if signature matched
ror.l #8,d1 ; setup to restore, kill some time
eieioSTP
move.b #12,bCtl(a2) ; point to register 12, time const low
ror.l #8,d1 ; position saved low byte of time const
eieioSTP
move.b d1,bCtl(a2) ; restore original time const low byte
ror.b #8,d1 ; kill some time, non-destructive
eieioSTP
move.b #13,bCtl(a2) ; point to register 13, time const high
lsr.l #8,d1 ; get the high byte
eieioSTP
move.b d1,bCtl(a2) ; restore original time const high byte
lsr.l #8,d1 ; test signature for match
rts6 ; all done
;_______________________________________________________________________
;
; Routine: TestForIOP
; Inputs: A2 - Base address of IOP to test for.
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if IOP not found, or bus error.
; - 1 (beq) if valid IOP found.
;
; Destroys: D1, D2
; Called by: BSR6
;
; Function: Checks to see if the specified I/O registers point to an
; IOP. Since the IOP chip generates it's own DSACK, a Bus
; Error may occur if it doesn't exist, which would cause this
; routine to return through the bus error handler, indicating
; that an IOP doesn't exist. If no bus errors occur, we
; verify that a long word read from the IOPRamData register
; causes the IOPRamAddr register to incement by 4. All of the
; IOP registers used are saved and restored, making this test
; non-destructive.
;
;_______________________________________________________________________
TestForIOP ; A2 := Base address of IOP to test
eieioSTP
move.b iopStatCtl(a2),d1 ; save status/ctl register value
moveq.l #(1<<iopIncEnable)+(1<<iopRun),d2 ; mask for bits to save
and.b d1,d2 ; get those bits
swap d1 ; save old status ctl reg
eieioSTP
move.w iopRamAddr(a2),d1 ; save Ram Address register value
ori.b #(1<<iopIncEnable),d2 ; enable increment <2.5>
eieioSTP
move.b d2,iopStatCtl(a2) ; enable register pointer incrementing
eieioSTP
tst.l iopRamData(a2) ; read and ignore 4 bytes of Ram
eieioSTP
move.w iopRamAddr(a2),d2 ; save updated Ram Address register value
eieioSTP
move.w d1,iopRamAddr(a2) ; restore Ram Address register value
subq.w #4,d2 ; back off the 4 byte increment
sub.w d1,d2 ; check for increment
swap d1 ; get status ctl reg
andi.b #-1-(1<<iopInt0Active)-(1<<iopInt1Active),d1
eieioSTP
move.b d1,iopStatCtl(a2) ; restore status/ctl register
tst.w d2 ; d2 = 0 if IOP found
eieioSTP
rts6
;_______________________________________________________________________
;
; Routine: TestForSCSIDMA
; Inputs: A2 - Base address of SCSI DMA to test for.
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if SCSI DMA not found, or bus error.
; - 1 (beq) if valid SCSI DMA found.
;
; Destroys: none
; Called by: BSR6
;
; Function: Checks to see if the specified I/O registers point to a
; SCSI DMA chip. Since the SCSI DMA chip generates it's own
; DSACK, a Bus Error may occur if it doesn't exist, which would
; cause this routine to return through the bus error handler,
; indicating that it doesn't exist. For now we just simply test
; to see if we can read the control register without getting
; a bus error. If we are successful, we assume that the chip
; exists. This test may need to be improved in the future.
;
;_______________________________________________________________________
TestForSCSIDMA ; A2 := Base address of SCSI DMA to test
eieioSTP
tst.l $80(a2) ; try to read the control register
eieioSTP
cmp.b d1,d1 ; if no bus error, assume that it exists
rts6
; <58> rb, from Terror...
;_______________________________________________________________________ thru matching <T8>
;
; Routine: TestForSCSI96
; Inputs: A2 - Base address of SCSI Port to test.
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if SCSI 5380 not found, or bus error.
; - 1 (beq) if SCSI 5396 found.
;
; Destroys: none
; Called by: BSR6
;
; Function: Checks to see if we have a SCSI 5380 chip or the more advance
; SCSI 5394/5396 controller. The test is to access a register
; the 5394/5396 has that the 53c80 does not. An access to a non-existent
; address would cause us to BusError. Unfortunately, there is a possibility <T14>
; that a non-existent address is decoded by HW anyway so if we pass bus-err <T14>
; test we verify the contents of the regr with expected value for safety. <T14>
;
;_______________________________________________________________________
; the CMPI will be .NE. if the address we write to does not bus error, but is in <T14>
; reality, not there. So the CMPI above actually checks to see if the data stuck. <T14>
TestForSCSI96 ; A2 = Base address of SCSI port to test
eieioSTP
tst.b $c0(a2) ; try to read configuration #3 register (r/w)
eieioSTP
cmpi.b #$04, $c0(a2) ; ...verify data written in config. regr 3 <T14>
eieioSTP
rts6
;_______________________________________________________________________
;
; Routine: TestForRPU
; Inputs: A2 - Base address of RPU to test for.
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if RPU not found, or bus error.
; - 1 (beq) if valid RPU found.
;
; Destroys: D1,D2
; Called by: BSR6
;
; Function: Checks to see if the RPU (Ram Parity Unit) is present by writing
; to the WWP bit of the chip (the only r/w bit) and reading back,
; making sure bus capacitance doesn't make it look valid.
;
;_______________________________________________________________________
TestForRPU ;
eieioSTP
tst.b (a2) ; x First 4 reads are unique
eieioSTP
tst.b (a2) ; x
eieioSTP
tst.b (a2) ; PDCA Read out the parity daisy chain bits
eieioSTP
tst.b (a2) ; PDCB and toss them (no where to save them)
eieioSTP
st.b rpuReset(a2) ;reset the RPU serial pointer
eieioSTP
move.b (a2),d2 ;save the WWP bit
eieioSTP
st.b rpuReset(a2) ;reset the RPU serial pointer
eieioSTP
st.b (a2) ;set the WWP bit
eieioSTP
clr.b rpuReset(a2) ;force bus low, reset pointer
moveq #1,d1 ;check bit 0
eieioSTP
and.b (a2),d1 ;read WWP bit
seq.b d1 ;d1=FF if WWP bit was 0
beq.s @exit ;exit if WWP bit=0
eieioSTP
st.b rpuReset(a2) ;reset the RPU serial pointer
clr.b (a2) ;clear the WWP bit
eieioSTP
st.b rpuReset(a2) ;force bus high, reset pointer
moveq #1,d1 ;check bit 0
eieioSTP
and.b (a2),d1 ;read WWP bit
@exit
eieioSTP
st.b rpuReset(a2) ;reset pointer for exit
move.b d2,(a2) ;restore WWP bit
tst.b d1 ;test result
eieioSTP
rts6
;_______________________________________________________________________ <SM32>
;
; Routine: TestForMUNI
; Inputs: A2 - Address of the MUNI Control register to test
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if not a valid MUNI Control register, or bus error.
; - 1 (beq) if valid MUNI Control register found.
;
; Destroys: D1, D2
; Called by: BSR6
;
; Function: Checks to see if the specified MUNI Control register
; exists by writing to it and seeing if we get a bus error.
; If we do, then we have no MUNI.
; Since the MUNI chip generates it's own
; DSACK, a Bus Error may occur if it doesn't exist, which would
; cause this routine to return through the bus error handler,
; indicating that it doesn't exist. For now we just simply test
; to see if we can read the control register without getting
; a bus error. If we are successful, we assume that the chip
; exists. This test may need to be improved in the future.
;
;
;_______________________________________________________________________
TestForMUNI ; A2 := address of MUNI register to test
eieioSTP
tst.l MUNI_Control(a2) ; try to read the control register
eieioSTP
cmp.b d1,d1 ; if no bus error, assume that it exists
rts6
;_______________________________________________________________________ <SM53>
;
; Routine: TestForBart
; Inputs: A2 - Address of BART
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if no BART, or bus error.
; - 1 (beq) if BART found.
;
; Destroys: D1, D2
; Called by: BSR6
;
; Function: Checks to see if BART exists by accessing it and seeing if
; we get a bus error. If we do, then we don't have a BART. This
; test should be extended in the future to check the version register
; in BART.
;
;
;_______________________________________________________________________
TestForBart ; A2 := address of BART register to test
eieioSTP
tst.b (a2) ; try to read BART
cmp.b d1,d1 ; if no bus error, assume that it exists
eieioSTP
rts6
; <SM28> fau start
;_______________________________________________________________________
;
; Routine: TestForFPU
; Inputs: A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if FPU not found.
; - 1 (beq) if FPU available.
;
; Destroys: A6, D1, sfc
; Called by: BRA
;
; Function: Checks to see if an FPU is installed.
;
; NOTE: this routine is BRA'nched to, not BSR6'ed, so that A6 is
; available for trashing in this routine.
;
; NOTE2: this needed to be changed because with an 040LC you're
; no longer guaranteed to have an on-board FPU.
;_______________________________________________________________________
TestForFPU
IF ROMinRAM THEN ; <SM22> rb
movec CACR,d1 ; MacsBug does not like the fpu <SM22> rb
cmp.b d1,d1 ; code when booting from RAM <SM22> rb
bra FPUReturn ; <SM22> rb
ELSE ; <SM22> rb
; New, Improved method of on-the-fly checking for and FPU
movec VBR,d1 ; retrieve VBR
; The idea is to move VBR DOWN the difference between the F-Line and
; BusError, so that if you were to execute an F-Line instruction and
; couldn't handle it, you would end up fetching the address of the
; BusErrVector and going thru the BusErrVector. The BusErr handler
; expects A6 to contain the address of where it should return TO.
sub.l #Line1111-BusErrVct,d1; temporarily move VBR down
movec d1,VBR ; shuffle VBR for F-Line test
moveq #1,d1 ; non-zero value in D1 for later comparison
lea @noFPU,a6 ; where to come back to if you dont have an FPU
eieioSTP
FNOP ; execute suspect command
eieioSTP
clr.l d1 ; if you got here, you have an FPU
@noFPU move.l d1,a6 ; save D1
movec VBR,d1 ; return VBR to it's old value
add.l #Line1111-BusErrVct,d1
movec d1,VBR ; ... so everyone is happy
move.l a6,d1 ; restore D1
tst.b d1 ; return CCR.Z to CheckOptionals
@exit bra FPUReturn ; and return to CheckOptionals <SM28> fau end
ENDIF ; <SM22> rb
;_______________________________________________________________________
;
; Routine: GetVIAInputs
; Inputs: A0 - Pointer to Decoder Info record for this decoder
; D0 - DefaultBases flags for this decoder
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: D1 - Bits 31..24, inputs from VIA1, port A
; D1 - Bits 23..16, inputs from VIA1, port B
; D1 - Bits 15.. 8, inputs from VIA2, port A
; D1 - Bits 7.. 0, inputs from VIA2, port B
;
; Destroys: D2, A1
; Called by: BSR6
;
; Function: Reads the input ports for VIA 1 and 2 if they are supported
; by the current address decoder (which does not imply that
; they actually exist). If the are not supported, zeros will
; be returned, if they are supported, but do not exist, the results
; are unpredictable, but are most likely the value of a floating
; data bus. The values of the data direction registers are saved
; and restored, which makes this non-destructive.
;
;_______________________________________________________________________
GetVIAInputs
moveq.l #0,d1 ; initialize via info result
btst.l #VIA1Exists,d0 ; see if VIA1 exists
beq.s @noVIA1 ; if not, skip it
movea.l VIA1Addr(a0),a1 ; get the VIA1 base address
eieioSTP
move.b vBufA(a1),d2 ; save port A
eieioSTP
lsl.w #8,d2 ; make room for direction bits
move.b vDirA(a1),d2 ; save direction bits
move.b d2,d1 ; get prior direction bits
eieioSTP
and.b AvoidVIA1A(a0),d1 ; if we need to avoid any output, don't make them input
eieioSTP
move.b d1,vDirA(a1) ; change bits to inputs
eieioSTP
move.b vBufA(a1),d1 ; get port A inputs
eieioSTP
move.b d2,vDirA(a1) ; restore direction bits
lsr.w #8,d2 ; get saved port A
eieioSTP
move.b d2,vBufA(a1) ; restore port A
lsl.w #8,d1 ; make room for port B bits
eieioSTP
move.b vBufB(a1),d2 ; save port B
lsl.w #8,d2 ; make room for direction bits
eieioSTP
move.b vDirB(a1),d2 ; save direction bits
eieioSTP
move.b d2,d1 ; get prior direction bits
and.b AvoidVIA1B(a0),d1 ; if we need to avoid any output, don't make them input
eieioSTP
move.b d1,vDirB(a1) ; change bits to inputs
eieioSTP
move.b vBufB(a1),d1 ; get port B inputs
eieioSTP
move.b d2,vDirB(a1) ; restore direction bits
eieioSTP
lsr.w #8,d2 ; get saved port B
move.b d2,vBufB(a1) ; restore port B
eieioSTP
@noVIA1
swap d1 ; VIA1 info to high word
btst.l #VIA2Exists,d0 ; see if VIA2 exists
beq.s @noVIA2 ; if not, skip it
eieioSTP
movea.l VIA2Addr(a0),a1 ; get the VIA2 base address
eieioSTP
move.b vBufA(a1),d2 ; save port A
eieioSTP
lsl.w #8,d2 ; make room for direction bits
move.b vDirA(a1),d2 ; save direction bits
eieioSTP
move.b d2,d1 ; get prior direction bits
and.b AvoidVIA2A(a0),d1 ; if we need to avoid any output, don't make them input
eieioSTP
move.b d1,vDirA(a1) ; change bits to inputs
eieioSTP
move.b vBufA(a1),d1 ; get port A inputs
eieioSTP
move.b d2,vDirA(a1) ; restore direction bits
eieioSTP
lsr.w #8,d2 ; get saved port A
move.b d2,vBufA(a1) ; restore port A
eieioSTP
lsl.w #8,d1 ; make room for port B bits
move.b vBufB(a1),d2 ; save port B
eieioSTP
lsl.w #8,d2 ; make room for direction bits
move.b vDirB(a1),d2 ; save direction bits
eieioSTP
move.b d2,d1 ; get prior direction bits
and.b AvoidVIA2B(a0),d1 ; if we need to avoid any output, don't make them input
eieioSTP
move.b d1,vDirB(a1) ; change bits to inputs
eieioSTP
move.b vBufB(a1),d1 ; get port B inputs
eieioSTP
move.b d2,vDirB(a1) ; restore direction bits
eieioSTP
lsr.w #8,d2 ; get saved port B
move.b d2,vBufB(a1) ; restore port B
eieioSTP
@noVIA2
rts6 ; all done
;_______________________________________________________________________
;
; Routine: TestForSonic
; Inputs: A1 - Base address of Sonic to test.
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if Sonic not found, or bus error.
; - 1 (beq) if Sonic found.
;
; Destroys: none
; Called by: BSR6
;
; Function: Checks to see if we have a Sonic Ethernet chip. An access to a non-existent
; address MUST cause us to BusError.
;
;_______________________________________________________________________
TestForSonic ; A1 = Base address of Sonic Chip to test <H12 begin>
eieioSTP
tst.b (a1) ; try to read the Command Register
eieioSTP
bset #7,(a1) ; send a SW Reset to Sonic <H30><SM40>
eieioSTP
cmp d1,d1 ; set ccr.z because no bus error if we made it here
rts6 ; return with flags set
;_______________________________________________________________________
;
; Routine: TestForPatchROM
; Inputs: A1 - Base address of PatchROM to test.
; A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if PatchROM not found, or bus error.
; - 1 (beq) if PatchROM found.
;
; Destroys: a1
; Called by: BSR6
;
; Function: Checks to see if we have a PatchROM. An access to a non-existent
; address MUST cause us to BusError.
;
;_______________________________________________________________________
TestForPatchROM ; A1 = Base address of PatchROM to test <H12 begin>
eieioSTP
tst.b (a1) ; try to read the first byte
eieioSTP
movea.l $4(a1),a1 ; load signature into a1
eieioSTP
exg a1,d1 ; because we have no free registers
cmpi.l #'romp',d1 ; set ccr.z if signtures match
exg a1,d1 ; because we have no free registers
rts6 ; return with flags set
;__________________________________________________________________________________________________
;
; Routine: GetCPUIDReg
;
; Inputs: A6 - return address
; A5, A7, D7, VBR - setup for bus error handler
;
; Outputs: ccr.z - 0 (bne) if CPUID reg not found or bus error.
; - 1 (beq) if CPUID reg found.
; D0.w - CPUID if CPUID reg found.
;
; Destroys: D0, D1, A2
;
; Function: Checks for the existance of a CPU ID register. If one is found, it checks to see
; if the value in the register matches the expected value for the current decoder
; type. The register is a long word located at $5FFFFFFC, and contains the following
; information.
;
; bits 31-16: signature $A55A
; 15-12: design center
; 0 = high volume
; 1 = portables
; 2 = high end Macintosh
; 3 = RISC
; 11: extension
; 0=complete ID appears in this register
; 1=supplemental ID appears in VIA or equivalent
; 10- 0: ID
;__________________________________________________________________________________________________
IF hasCPUIDRegister THEN ; <SM24> rb <SM36> rb
GetCPUIDReg
IF ROMinRAM THEN ; <SM22> rb
move.l #$A55A2830,d0 ; ••• HACK, force Cyclone, make your <SM22> rb
cmp.w d0,d0 ; ModifyReadOnly hack here. Cyclone <SM22> rb
jmp (a6) ; needs this because the MMU is <SM22> rb
ENDIF ; hiding the CPUIDReg one we booted <SM22> rb
IF forSmurf THEN
; Read the CPUID bits from the via register. Orwells/djmemc both have
; via addrs at $50F0000 (but for smurfs, use $50000000)
movea.l #$50000000,a2 ; get the VIA1 base address
;now get the cpuid bits from the via register
move.b vBufA(a2),d2 ; save port A
lsl.w #8,d2 ; make room for direction bits
move.b vDirA(a2),d2 ; save direction bits
move.b d2,d1 ; get prior direction bits
move.b #0,vDirA(a2) ; change bits to inputs
move.b vBufA(a2),d1 ; get port A inputs
move.b d2,vDirA(a2) ; restore direction bits
lsr.w #8,d2 ; get saved port A
move.b d2,vBufA(a2) ; restore port A
; d1.b now contains the cpuid bits. so use $56 to mask out leaving us with the
; cpuid bits PA6, PA4, PA2, PA1
andi.b #$56,d1 ; d1.b now contains the cpu id bits from the via
; now find out if we are on a machine with a djmemc decoder or and orwell.
; djmec have a 12 bit register, bits 11..9 contain the version number for the djmemc...
; Game Plan: read from the 12 bit register. if bits 11..9 = 010 then djmec
lea #MEMCAddr,a2 ; Orwell or djmec decoder addr.
move.l MEMCIntleaveEnable(a2),d0 ; read the 12 bit register at the base of DJMEMC/Orwell
andi.w #$0E00,d0 ; mask out all bits except version bits at bit 11..9
cmpi.w #$0200,d0 ; the version number for djmec is 010 for bits 11..9
beq.s @tryCentris610 ; if equal than on djmec machine..via id bits will match
; those for wombat machines
@tryQ700
cmpi.b #$40,d1 ; is it a quadra700
bne.s @tryQ900
MOVE.W #(cpuIDRISC)|\ ; CPU ID: RISC design center
$1235,D0 ; return emulator CPU ID
BRA @success
@tryQ900
cmpi.b #$50,d1 ; is it a quadra900
bne.s @tryQ950
MOVE.W #(cpuIDRISC)|\ ; CPU ID: RISC design center
$1236,D0 ; return emulator CPU ID
BRA @success
@tryQ950 ; if here it must be Q950
MOVE.W #(cpuIDRISC)|\ ; CPU ID: RISC design center
$1237,D0 ; return emulator CPU ID
BRA @success
@tryCentris610
cmpi.b #$40,d1 ; is it a Centris610?
bne.s @tryCentris650
MOVE.W #(cpuIDRISC)|\ ; CPU ID: RISC design center
$1204,D0 ; return emulator CPU ID
BRA @success
@tryCentris650
cmpi.b #$46,d1 ; is it a Centris650?
bne.s @tryQ800
MOVE.W #(cpuIDRISC)|\ ; CPU ID: RISC design center
$1200,D0 ; return emulator CPU ID
BRA @success
@tryQ800
cmpi.b #$12,d1 ; is it a Quadra800?
bne.s @tryQ610
MOVE.W #(cpuIDRISC)|\ ; CPU ID: RISC design center
$1201,D0 ; return emulator CPU ID
BRA @success
@tryQ610
cmpi.b #$44,d1 ; is it a Quadra610?
bne.s @tryQ650
MOVE.W #(cpuIDRISC)|\ ; CPU ID: RISC design center
$1202,D0 ; return emulator CPU ID
BRA @success
@tryQ650 ;if here assume Smurf card is in Q650
MOVE.W #(cpuIDRISC)|\ ; CPU ID: RISC design center
$1203,D0 ; return emulator CPU ID
BRA @success
ENDIF ; forSmurf
LEA CPUIDReg,A2 ; Get CPU ID reg address
; FIRST - try to read it as a LONG. <SM43>,<SM44>
MOVE.L (A2),D0 ; read the register (bus err if it doesn't exist)
MOVEQ #0,D1 ; clear pattern register
@FlipBits ; LOOP (to write different patterns in CPUID reg)
MOVE.L D1,(A2) ; write next pattern to CPUID register location
CMP.L (A2),D0 ; does it read back the same as the first time?
BNE.S @tryPDMIDReg ; -> no. try reading it the other way.
NOT.L D1 ; flip the bits in the write pattern
BNE.S @FlipBits ; -> try the next write pattern
SWAP D0 ; look at the signature
CMPI.W #cpuIDSig,D0 ; is it a valid signature?
BNE.S @tryPDMIDReg ; -> no. try reading it the other way.
SWAP D0 ; look at the decoder-specific stuff
bra @success ; yay, we're done.
@tryPDMIDReg ; SECOND - see if it's a byte-wide only reg (like on PDM)
move.b (a2), d0 ; read high byte (bus err if it doesn't exist)
move.b #$6a, (a2) ; write/read to be sure it's really there
cmp.b (a2), d0 ; match previous read?
bne @noCPUIDReg ; no. must not really be the CPUID reg.
lsl.l #8, d0 ; shift high byte over
move.b 1(a2), d0 ; read next byte
move.b #$6f, 1(a2) ; write/read to be sure it's really there
cmp.b 1(a2), d0 ; match previous read?
bne @noCPUIDReg ; no. must not really be the CPUID reg.
lsl.l #8, d0 ; shift next byte over
move.b 2(a2), d0 ; read next byte
move.b #$65, 2(a2) ; write/read to be sure it's really there
cmp.b 2(a2), d0 ; match previous read?
bne @noCPUIDReg ; no. must not really be the CPUID reg.
lsl.l #8, d0 ; shift next byte over
move.b 3(a2), d0 ; read last byte
move.b #$20, 3(a2) ; write/read to be sure it's really there
cmp.b 3(a2), d0 ; match previous read?
bne @noCPUIDReg ; no. must not really be the CPUID reg.
swap d0 ; check the signature
cmpi.w #cpuIDSig, d0 ; is it valid?
bne @noCPUIDReg ; nope, exit with Z cleared.
swap d0 ; yay! we're probably a PDM! (how cool if we are.)
cmpi.w #$3010, d0 ; could we be an EVT2 but don't know it? <SM45>
bne @success ; nope
move.b $50F32008, d1 ; read SCSI DMA ctl reg
movea.w d1, a2 ; remember the original setting
ori.b #$0C, d1 ; poke the extra bits
move.b d1, $50F32008 ; save the updated value
nop
move.b $50F32008, d1 ; read SCSI DMA ctl reg again
andi.b #$0C, d1 ; did they stick?
beq.s @success ; nope, don't dick with the CPUID
move.w a2, d1 ; restore the original setting
move.b d1, $50F32008
nop
@ck4FastSCSI
move.b #$02, $50f11030 ; do cResetChip cmd
nop
move.b #$00, $50f11030 ; cNOP required after HW or SW reset
move.b #$40, $50f110b0 ; turn on Features enable then,
move.b #$80, $50f11030 ; send a DMA NOP command then,
nop
cmp.b #$A2, $50f110e0 ; read the SCSI chip ID - an FC96?
beq.s @isFastSCSI ; yes -> we have Fast SCSI (i.e. we're on a Cold Fusion)
@noFastSCSI
move.b #$02, $50f11030 ; cResetChip again
nop
move.b #$00, $50f11030 ; cNOP required after HW or SW reset
move.b #$11, d0 ; we're an AMIC2 - change CPUID to $3011
bra.s @success ;
@isFastSCSI
move.b #$02, $50f11030 ; cResetChip again
nop
move.b #$00, $50f11030 ; cNOP required after HW or SW reset
move.b #$13, d0 ; we're a Cold Fusion - change CPUID to $3013
@success
IF forSTP601 THEN
ori.w #(cpuIDRISC),d0
ENDIF
CMP.W D0,D0 ; set ccr.z to indicate success
@noCPUIDReg JMP (A6) ; END
ENDIF ; <SM24> rb
end