mac-rom/OS/Universal.a

2130 lines
91 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 norom ; if not, we're screwed
; 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>
norom
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>
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>
beq.s @CudaDone
cmpi.l #$3000000, D0
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>
ENDIF ; <SM22> rb
@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)+$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
dc.l (GotBusError-BaseOfRom)+$FFC00000 ; base of NewWorld ROM?
GotBusError btst.l #beok,d7 ; indicate that bus error occured
move.l a5,a7 ; restore stack
rts6 ; return
;_______________________________________________________________________
;
; Routine: InitVIAs aad8
; 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
;
; 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)+,vBufA(a2) ; init output port A <P9> gjs
eieioSTP
move.b (a3)+,vDirA(a2) ; init direction for port A <P9> gjs
nop
eieioSTP
move.b (a3)+,vBufB(a2) ; init output port B <P9> gjs
eieioSTP
move.b (a3)+,vDirB(a2) ; init direction for port B <P9> gjs
nop
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
@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
nop
eieioSTP
move.b (a3)+,vBufB(a2) ; init output port B
eieioSTP
move.b (a3)+,vDirB(a2) ; init direction for port B
nop
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
rts6
;_______________________________________________________________________
;
; Routine: GetHardwareInfo ab4e
; 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
cmpi.l #'Hnfo',([$68FFEFD0],$70) ; NKHWInfo.Signature, fix this later
bne.s @tryOldWay
import InfoNewWorld
biglea InfoNewWorld,a1
bra Matched
@tryOldWay
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
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 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 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
Move.L BasesValid1(A1), D0
BTst.L #$1E, D0
BEQ @skipAllThis
MoveA.L ([$68FFEFD0],$8), A0 ; NKHWInfo.UniversalInfoTableBase
Move.B $12(A1), D0
Move.B D0, $12(A0)
Move $14(A1), D0
Move D0, $14(A0)
Move.B $16(A1), D0
Move.B D0, $16(A0)
Move $10(A1), D0
Or D0, $10(A0)
MoveA.L (A0), A2
AddA.L A0, A2
Move.L $24(A1), D0
Or.L D0, $24(A0)
Or.L D0, -$1C(A2)
Move.L $28(A1), D0
Or.L D0, $28(A0)
Or.L D0, -$18(A2)
Move.L $2C(A1), D0
Or.L D0, $2C(A0)
Or.L D0, -$14(A2)
MoveA.L A1, A2
SubA.L A0, A2
Move.L A1, D0
MoveA.L $8(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $8(A0)
MoveA.L D0, A1
MoveA.L $4(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $4(A0)
MoveA.L D0, A1
MoveA.L $C(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $C(A0)
MoveA.L D0, A1
MoveA.L $38(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $38(A0)
MoveA.L D0, A1
MoveA.L $3C(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $3C(A0)
MoveA.L D0, A1
MoveA.L $40(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $40(A0)
MoveA.L D0, A1
MoveA.L $44(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $44(A0)
MoveA.L D0, A1
MoveA.L $48(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $48(A0)
MoveA.L D0, A1
MoveA.L $4C(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $4C(A0)
MoveA.L D0, A1
MoveA.L $50(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $50(A0)
MoveA.L D0, A1
MoveA.L $64(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $64(A0)
MoveA.L D0, A1
MoveA.L $5C(A1), A1
Tst.L A1
BEQ.B (* + $4)
AddA.L A2, A1
Move.L A1, $5C(A0)
MoveA.L D0, A2
MoveA.L A2, A1
Move.B $68(A1), D0
Move.L D0, $68(A0)
MoveQ.L #$0, D0
Move ([$68FFEFD0],$76), D0 ; NKHWInfo.CPU_ID
Move D0, $58(A0)
biglea CPUIDProductLookup,a2
Lea.L $8(A2), A2
Tst.L (A2)
BEQ.B @is_single_entry_table
Cmp.L (A2), D0
BNE.B (* + -$A)
Move.L $4(A2), D0
Bra.B @common_path
@is_single_entry_table
Move.L $60(A1), D0
@common_path
Move.L D0, $60(A0)
MoveA.L A0, A1
@skipAllThis
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 FoundMatch ; if found, return the info
CheckBases
move.l DefaultBases(a0),d0 ; get the default base flags
movea.l a6,a0 ; save return address
bclr.l #VIA2Exists,d0
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
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
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
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>
; 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 ab4e
;
; 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
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 aec6
; 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 aeca, TestVIERWrap aecc
; 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
nop
eieioSTP
@loop neg.b d1 ; pattern of bit to clear
eieioSTP
move.b d1,(a2) ; clear the lowest order bit
nop
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)
nop
eieioSTP
move.b d1,(a2) ; restore original VIER value
eieioSTP
lsr.w #8,d1 ; 0 if VIER found
rts6
;_______________________________________________________________________
;
; Routine: TestForSCSIDMA aefe
; 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 af06
; 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: GetVIAInputs af12
; 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
nop
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
nop
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
nop
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
nop
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: GetCPUIDReg afb4
;
; 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
move.l ([$68FFEFD0],$70),d0 ; NKHWInfo.Signature
cmpi.l #'Hnfo',d0
bne.s @noHnfo
move ([$68FFEFD0],$76),d0 ; NKHWInfo.CPU_ID
bra @eq
@noHnfo
bra.s @ne
@eq
cmp d0,d0
@ne
rts6
ENDIF ; <SM24> rb
end