mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-21 13:31:15 +00:00
2861 lines
120 KiB
Plaintext
2861 lines
120 KiB
Plaintext
;__________________________________________________________________________________________________
|
||
;
|
||
; 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 Don’t use onMvMac conditional, Modern Victorian never existed.
|
||
; <54> 10/1/91 JSM Don’t 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
|
||
|