mac-rom/OS/StartMgr/USTNonCritTsts.a

6767 lines
256 KiB
Plaintext
Raw Normal View History

;
; File: USTNonCritTsts.a
;
; Contains: This file includes the non-critical test routines. Some of these are run at system
; startup with errors being logged to parameter ram. All of them are available to the
; Test Manager through the NJump Test Table.
;
; Note that all procedures called from this routine must preserve the upper word of d7
; and the value in a7. (When exitting a procedure, the stack must be where it was when
; it entered.)
;
; Written by: Dave Holzer, Russ Emmons, Gary Rensberger, Steve Smith, Mark Appleman, et al.
;
; Copyright: <09> 1983-1990, 1992-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM16> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
; machines.
; <SM15> 11/8/93 JRH boxDBLite16 is now boxPowerBookDuo250. boxDBLite20 is now
; boxPenLite.
; <SM14> 8/17/93 SAM Placed conditional forSmurf around the smurf stuff.
; <SM13> 8/12/93 BG Removed reference to boxWLCDc1 as such a thing will never exist.
; Updated other boxflags to their "official" names.
; <SM12> 8/11/93 KW just changed the name of boxRISCWombat to boxRiscCentris650
; <SM11> 8/4/93 JDR Removed redefinitions of private sound info, and now include
; SoundPrivate.a
; <SM10> 01-11-93 jmp Updated various BoxFlag names.
; <SM9> 12/23/92 RC Added Support for Smurf on Wombat
; <SM8> 12/06/92 HY Added LC II support.
; <SM7> 11/3/92 rab Add comments for Horror roll in <SM6>. Comments follow:
; <H24> 10/6/92 NJV Added support in Sound Interrupt test for testing both channels
; on a Wombat.
; <H23> 10/5/92 NJV Fixed some bugs in the Sound Interrupt diagnostic tests that
; were causing interrupts to be lost.
; <H22> 9/30/92 SES Modified TestSndInts so that it works with Wombat's
; implementation of Batman. The ordering in which the sound
; interrupts were disabled, cleared, and re-enabled needed to be
; modified. Yet to do: add check for Wombat sound play on channel
; B.
; <H21> 8/26/92 AL Fixed a tiny bug in TestClut so that I don't accidentally turn
; off the dot clock if I didn't actually turn it on. Made
; TestSndInts work on Vail.
; <H20> 8/12/92 AL Fixed TestVRAM to preserve the sizing info for Vail (in case the
; OS is running and we don't want to trash video when we're done),
; fixed TestCLUT to turn on/off the dot clock if necessary (for
; Sonora only).
; <H19> 8/10/92 SWC Made sure that the ifIRQ bit is set when restoring RBV interrupt
; enable registers, since some versions read the bit as zero.
; <H18> 8/2/92 AL Fixed TestVRAM for DBLite.
; <H17> 7/27/92 AL Enhanced SizeVRAM to account for various screen types, fixed up
; PG&E Selftest to return errors for both the self test and/or
; communication problems with PG&E.
; <H16> 7/15/92 AL Fixed TestASC to support DBLite.
; <H15> 7/14/92 AL Fixed the floppy eject problem (related to Swim2), made a one
; line change to TestVRAM, restored the boxUnknown flag to the FPU
; table in Float_Test, fixed the TestASC and TestRBV routines to
; support Vail.
; <H14> 6/26/92 BG Added WLCD20, WLCD25, WLCDc1, Wombat20, and Wombat25 to the list
; of machines with optional FPUs.
; <H13> 6/17/92 AL Polished up the PG&E and GSC tests for DBLite.
; <H12> 6/7/92 AL Fixed a minor problem with a <H11> comment that wasn't separated
; from the code by a semicolon. Hardly worth mentioning.
; <H11> 6/7/92 AL Enhanced the SizeVRAM routine to support Sonora. Fixed the
; TestVRAM routine to force the Sonora size bits to 256k of VRAM
; before leaving so that sound will work correctly until the
; "real" VRAM sizing routine is called. Added boxVail25 and
; boxVail16 to the table of machines with optional FPUs for the
; FPU test routine.
; <SM6> 11/3/92 rab Roll in Horror changes.
; <SM5> 10/25/92 HY Add support for boxMacLCII boxflag.
; <SM4> 5/23/92 RB Making Cyclone changes...<P4> 2/10/92 (GS) Added the CudaTest
; code in the EgretTest modual. A test is executed to determine
; the FW type, then the appropiate test is executed.
; <SM3> 5/1/92 kc Roll in Horror. Comments Follow:
; <H10> 3/17/92 SWC Renamed boxDBLite->boxDBLite25 and boxDBLiteLC->boxDBLite33, and
; added boxDBLite16 and boxDBLite20 to the optional FPU list.
; <H9> 3/6/92 AL Made enhancements to the TestSWIM noncritical test to test the
; Swim2
; PRAM if a Swim2 is present. Also, added two new non-critical
; tests for DBLite - one that tests the registers of the GSC, and
; another that executes the PG&E self test. Changed the BSR6
; branches to TM_xxx routines (in the file USTPram.a) to BigBSR6
; branches, because that file was moved into USTStartTest1.a and
; ended up too far away.
; <H8> 01/27/92 jmp Conditionalized the PROC parts of this file for use in lining up
; the UST part of HORROR with that of TERROR/Zydeco.
; <H7> 1/14/92 SWC Added DB-Lite LC to the list of boxes with optional FPU. Changed
; boxTIM to boxPowerBook170.
; <H6> 12/16/91 SWC Changed DB-Lite's VRAM size to 256K now that we have GSC.
; <H5> 11/25/91 CCH Use standard VIA equates.
; <H4> 10/28/91 SWC Added code to SizeVRAM to support DB-Lite.
; <H3> 9/10/91 CMP Added code to test for SWIM2 in TestSWIM
; <H2> 8/22/91 SWC Added DB-Lite to list of boxes with optional FPU.
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
; Pre-HORROR ROM comments begin here.
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
; <T10> 4/22/91 BG Rolled in Scott Smyers changes: Fixed the SCC internal loopback
; test for Spike at startup.
; <T9> 4/13/91 BG Fixed the sound interrupt test for Spike and Eclipse by adding
; VIA accesses to the delay loops to make the timeout periods
; machine independent, and also by fixing an inconsistency in the
; VIA register used for interrupt status.
; <T8> 4/2/91 CCH Rolled in changes from Scott Smyers: Added the SizeVRAM routine
; from USTSartup and made it work with DAFB. Changed the VRAM test
; to use the SizeVRAM routine and also made it work with DAFB video.
; <T7> 3/13/91 CCH Rolled in RBI changes from Scott Smyers.
; <T6> 2/18/91 djw Rolled in Scott Smyers' changes
; <T5> 1/14/91 CCH Rolled in Scott Smyers' changes.
; <T4> 12/14/90 BG Modified Float_Test in the short term to NOT test FPUs if
; running on an 040. The test needs to be modified to deal with
; the fact that to handle Floating Point correctly, the 040 FP
; emulation package needs to be installed. A non-trivial task, and
; I'll defer to Scott to make it happen.
; <T3> 12/14/90 HJR Removed file wide WITH statement and localized it where
; necessary. Made FPU equates local and made sound interrupt test
; work with both RBV and real VIA 2.
; <T2> 12/11/90 JJ Mac LC: Changes references to VISAChipBit to V8ChipBit.
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
; Pre-TERROR ROM comments begin here.
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
; <11> 6/7/90 CV Rolling in changes from mainproj. Original comments below.
; {20} 6/6/90 SS Added a preload of the VIA T1 and T2 upper count registers to
; avoid potential loss of interrupt.
; {19} 6/6/90 SS Modified the ASC register test so that it now applies a mask to
; the read register data before comparing it with the written
; value.
; <10> 5/31/90 BA Rolling in changes from Reality. Original comments below.
; {18} 5/30/90 SS Fixed the sound interrupt test and ASC test so that these two
; tests now run on an Ericson with discreet sound-input, Ericson
; with batman and Elsie.
; <9> 5/18/90 CV Rolling in changes from mainproj. Original comments below.
; {17} 5/11/90 SS Fixed the sound interrupt test so that it runs on both an Elsie
; and an Ericson. Also changed the places where the ASC registers
; are accessed to use equates defined in HWPrivateEqu, instead of
; hardcoded offsets.
; {16} 5/9/90 SS Fixed the Egret test to work with the new Egret I/F routines
; that were modified to help the read/write PRAM routines work.
; {15} 5/7/90 SS Removed the import of TMVectors because it wasn't used in here
; anyway.
; <8> 4/27/90 CV Rolling in changes from mainproj. Original comments below.
; {13} 4/20/90 SS Changed SCSI test to use SCSI equates in HWPrivateEqu and
; changed Egret test to use equates in EgretEqu.a as per
; suggestions which came up in the code review of 4/16/90.
; {12} 4/17/90 SS Modified the RBV test so that it can also handle the VISA RBV.
; Also made some register offset addressing modes explicite in
; this test, while correcting an error in loading the register
; used as the offset.
; <7> 4/13/90 JJ Change value in sndrdVISA table of the ASC non-critical test to
; avoid generating white noise at boot time.
; <6> 4/10/90 JJ Rolling in changes from mainproj. Original comments below.
; {11} 4/9/90 SS Fixed the PRAM test so that it correctly reports errors found in
; the first half of PRAM.
; {10} 3/15/90 SS Added a runtime check to the FPU test so that it doesn't fail on
; systems that have no FPU. (Instead it indicates that it is an
; invalid test for the machine).
; <5> 3/12/90 CV Rolling in changes from mainproj. Original comments below.
; {9} 3/9/90 SS Made the PRAM test more tolerant of power fails during RBI.
; Moved the SCSI register equates into STEqu.a.
; <8> 2/27/90 SS Added new Egret test and sound interrupt test. Added new sound
; register test data for use with a VISA decoder. Changed the
; record FIFO test algorithm so that it uses a changing pattern
; rather than a fixed one. Import some Egret interface support
; routines for use in the Egret test (if it has an Egret).
; <7> 2/16/90 SS Added flags to statements which were changed to support Ericson.
; <6> 2/12/90 MA Added stuff to ASCTest to test FIFO, sound-in FIFO, and extra
; sound-in reg. This test wont run on Elsie yet.
; <5> 1/23/90 MA Fixed incorrect loading of romBlockPtr (i.e. a3) in
; FMCCacheTest.
; <4> 1/17/90 MA For FMCCacheTest: now flushing extern. cache, cleaning
; up better, and returning a more informative error code.
; <3> 1/3/90 SES Made changes for Mark Appleman. Added FMCCacheTest,
; removed OSSCntrTest.
; <3> 1/3/90 SES Made changes for Mark Appleman. Added FMCCacheTest, removed
; OSSCntrTest.
; <2.3> 12/7/89 GMR NEEDED FOR ZONE5: Made PGC test compatible with new NMI handler
; in place now, keeping a0 pointing to the universal base address
; table.
; <2.2> 11/21/89 MSH Changed the hasPowerMgr to onHcMac, which is more accurate in
; this instance.
; <2.1> 11/13/89 SES Added diagnostics for FMC shift register, OSS registers, counter
; and interrupt.
; <2.0> 10/30/89 MSH Removed ancient power manager call to power up the ASC, in the
; ASC test.
; <1.9> 10/7/89 GMR NEEDED FOR ZONE5: Fixed non-critical tests which use interrupts,
; saving VIA1 state, so they'll work with the Test Manager Trap
; interface.
; <1.8> 8/22/89 GMR Fixed conditional bug from previous change
; <1.7> 8/22/89 GMR Added in the rest of Fremonts non-critical tests (that didn't
; need to be universalized). Changed references of (a3,d3) to
; (a3,d3.l) to fix SCC tests on hcMac.
; <1.6> 7/15/89 GMR Changed isUniversal conditionals to make consistant with others.
; <1.5> 7/15/89 GMR Cleared interrupt levels for all OSS interrupt registers, and
; disabled all VIA2 interrupts in the VIATest and SCCTimerTest.
; <1.4> 6/28/89 GMR Added OSS support for VIA and SCCTimer tests. Removed code which
; allocates VBR on stack (VBR is now setup in RAM by USTStartup.a)
; in SCC and VIA tests. SCCLoopTest now uses 8 patterns instead of
; 256.
; <1.3> 6/12/89 GMR Passing IOP SCC base into SetIOPBypass now.
; <1.2> 6/11/89 GMR Made SetIOPBypass universal, getting base from GetHardwareInfo
; <1.1> 6/11/89 GMR Removed INCLUDES, now in header file which includes all others.
; <1.0> 6/11/89 GMR Added Universal StartTest files for first time to EASE, based on
; version 2.0 of Fremonts code.
;
; To Do:
;
;-----------------------------------------------------------------------------------------------
include 'SoundPrivate.a'
NonCritProc PROC ;
EXPORT MapRamDataTest
EXPORT MapRamUniqTest
EXPORT VRamAddrTest
EXPORT VRamDataTest
EXPORT SCCRegTest
EXPORT SCCTimerTest
EXPORT SCCLoopTest
EXPORT ViaTest
EXPORT TestSCSI
EXPORT TestASC
EXPORT PramTest ;
EXPORT TestRBV ;
EXPORT TestSWIM ;
EXPORT TestPGC ;
EXPORT Float_Test ;
EXPORT FMCRegTest ;<2.1>
EXPORT FMCCacheTest ;<3>
EXPORT OSSRegTest ;<2.1>
EXPORT OSSIntTest ;<2.1>
EXPORT RPUTest ;<gmr>
EXPORT EgretTest ;<8>
EXPORT TestSndInts ;<8>
EXPORT TestCLUT ;<21>
EXPORT TestVRAM ;<23>
EXPORT TestC96 ;<T8>
EXPORT TestGSCRegs
EXPORT PGESelfTest
EXPORT TestCSCRegs
EXPORT SetSCCIOPBypass ;
IMPORT QuasiPwrMgr
IMPORT TM_SendByte ;<8>
IMPORT TM_GetByte ;<8>
IMPORT TM_Wait ;<8>
IMPORT CudaReadByte ;<P3><SM4> rb
IMPORT CudaWriteByte ;<P3><SM4> rb
IMPORT RdXByte ;
IMPORT WrXByte ;
IMPORT ClkWpOff ;
IMPORT IntLevel7
IMPORT SendEgretCmd ;<SM6>
IF hasPowerMgr THEN ; <v1.1>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; #83: VramAddrTest: will verify addressing of 32kx8 video sram for laguna [v1.2>
; by walking a one and zero on the video ram address bus
; with each address having a unique data pattern which will
; point to the address line under scrutiny
;
; entry: a6.l = return address
; d6.l = 0 (error code)
;
; exit: if pass
; d6.l = 0
; else
; d6.l = the following
; d6 upper word failed address (16-bit)
; d6 msb of lower word contains data written
; d6 lsb of lower word contains data read
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
VramAddrTest ;
clr.l d0 ;clear for later
lea.l ScreenLow,a0 ;ptr to base of video ram
move.w #$4000,d0 ;address offset
moveq.l #$1e,d1 ;walking ones data
move.w #$e0,d2 ;walking zero's data
@wloop move.b d1,(a0,d0.w) ;write wo data to walking one address
eori.w #$7fff,d0 ;adjust address to walking zero now
move.b d2,(a0,d0.w) ;now write wz data to wz address
subq.b #1,d1 ;adjust wo data to point to next address line
ror.w #4,d2 ;move address line indicator nibble for adjust
subq.b #1,d2 ;and adjust data to point to next address line
rol.w #4,d2 ;now put it back to normal for write
eori.w #$7fff,d0 ;get orignal wo address
lsr.w #1,d0 ;adjust to next address line
bne.s @wloop ;do all ones/zeros addresses
move.w #$4000,d0 ;address offset
moveq.l #$1e,d1 ;walking ones data
move.w #$e0,d2 ;walking zero's data
@rdloop move.b (a0,d0.w),d3 ;read from wo address
cmp.b d1,d3 ;are they the same
bne.s @failones ;no, failed ones
eori.w #$7fff,d0 ;adjust address to zeros
move.b (a0,d0.w),d3 ;read wz address
cmp.b d2,d3 ;
bne.s @failzeros ;no, failed zeros
subq.b #1,d1 ;adjust wo data to point to next address line
ror.w #4,d2 ;move address line indicator nibble for adjust
subq.b #1,d2 ;and adjust data to point to next address line
rol.w #4,d2 ;now put it back to normal for write
eori.w #$7fff,d0 ;adjust address back to original wo's
lsr.w #1,d0 ;adjust to next address line
bne.s @rdloop ;do till done
bra.s @done ;if here, must be done
@failones ;
move.w d0,d6 ;get failed ones address
moveq.l #16,d2 ;shift val
asl.l d2,d6 ;move failed address to upper upper word
move.b d1,d6 ;get ones data write value
asl.w #8,d6 ;move it to upper byte of low word
move.b d3,d6 ;put ones data read value and put in lsb
bra.s @done ;and finish
@failzeros ;
move.w d0,d6 ;get failed zeros address
moveq.l #16,d1 ;shift val
asl.l d1,d6 ;move failed address to upper upper word
move.b d2,d6 ;get zeros data write value
asl.w #8,d6 ;move it to upper byte of low word
move.b d3,d6 ;put zeros data read value and put in lsb
@done RTS6 ;rtn with status
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; #82: VramDataTest will verify video ram using mod3test and revmod3test [v1.2>
;
;
; entry: a6.l = return address
; d6.l = 0 (error code)
;
; exit: if pass
; d6.l = 0
; else
; d6.b = bad bit mask
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
VramDataTest ; [v1.3>
move.l a6,a3 ;save rtn addr
lea.l HcVideoStart,a0 ;start of video ram
lea.l HcVideoEnd,a1 ;end of video ram + 1
lea.l @464,a6 ;save rtn address
jmp Mod3Test ;do mod3 ram test on video ram
@464 tst.l d6 ;any error
bne.s @vidramfail ;yes, critical fail
lea.l @vidramfail,a6 ;save rtn address
jmp RevMod3Test ;do Revmod3 ram test on video ram
@vidramfail ;
move.l d6,d0 ;get results
asr.w #8,d0 ;and adjust for 8-bit wide memory
or.b d0,d6 ;final bit mask in lsb of d6
move.l a3,a6 ;restore rtn addr [v1.3>
RTS6 ;rtn to caller
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; #80: MapRamDataTest will write and verify various patterns to the laguna [v1.2>
; 16x3 mapper ram (really registers)
;
; entry: a6.l = return address
; d6.l = 0
;
; exit: if pass
; d6.l = 0
; else
; d6 bytes 3 & 2 = register offset address
; d6 byte 1 = value written
; d6 byte 0 = value read
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MapRamDataTest ; [v1.2>
lea.l MapperBase,a0 ;ptr to mapper base
lea.l MapTestTable,a1 ;start of test patterns
move.w maptesttablesize,d0 ;entries in table
@mwlp2 moveq.l #1,d1 ;init map reg offset
move.b (a1,d0.w),d2 ;get a pattern
@mwlp1 move.b d2,(a0,d1.w) ;write it to mapper reg
addq.l #2,d1 ;bump register offset to next reg
cmp.b #$1f,d1 ;all registers written
ble.s @mwlp1 ;no, do another
moveq.l #1,d1 ;init reg offset
@mrdlp1 move.b (a0,d1.w),d3 ;read a reg
and.b #7,d3 ;mask irrellevant
cmp.b d2,d3 ;is read = write
bne.s @failmapram ;no, failed
addq.l #2,d1 ;bump reg offset
cmp.b #$1f,d1 ;all registers read
ble.s @mrdlp1 ;no, read another
dbra d0,@mwlp2 ;do all patterns
bra.s @passmap ;must have passed
@failmapram ;
move.b #16,d0 ;shift val
move.b d1,d6 ;get register offset
asl.l d0,d6 ;adjust it to upper word
move.b d2,d6 ;get write val
asl.w #8,d6 ;adjust it to msb of low word
move.b d3,d6 ;and finally the value read from map ram
@passmap ;
RTS6 ;return to caller
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; #81: MapRamUniqTest will verify that laguna 16x3 mapper ram (really registers) [v1.2>
; is unique
;
; entry: a6.l = return address
; d6.l = 0
;
; exit: if pass
; d6.l = 0
; else
; d6 bytes 3 & 2 = register offset address
; d6 byte 1 = value written
; d6 byte 0 = value read
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MapRamUniqTest ; [v1.2>
lea.l MapperBase,a0 ;ptr to mapper base
lea.l MapTestTab2,a1 ;test data
move.l a1,a2 ;keep a copy
moveq.l #1,d1 ;init reg offset
@wlpf move.b (a1)+,(a0,d1.w) ;write data using fwd direction
addq.l #2,d1 ;bump reg offset
cmp.b #$1f,d1 ;all regs written
ble.s @wlpf ;no, do another
lea.l @rd1,a3 ;get rtn address
bra.s @rdfwd ;verify by reading
@rd1 tst.l d6 ;any errors
bne.s @mapuniqfail ;yes,fail
lea.l EndMapTestTab2+1,a1 ;now start at end of table
moveq.l #$1f,d1 ;set reg offset
@wlpr move.b -(a1),(a0,d1.w) ;write it in backwards
subq.l #2,d1 ;dec reg offset
bpl.s @wlpr ;all regs written
lea.l @mapuniqfail,a3 ;get retn addr
bra.s @rdfwd ;verify again
@mapuniqfail ;
RTS6 ;
;subroutine to read/verify mapper ram uniqueness
@rdfwd moveq.l #1,d1 ;reg offset
move.l a2,a1 ;get table base
@rdfwd1 move.b (a0,d1.w),d3 ;read val from map ram
and.b #7,d3 ;mask irrelevant
cmp.b (a1)+,d3 ;write=read
bne.s @failrd ;no failed
addq.l #2,d1 ;bump reg offset
cmp.b #$1f,d1 ;all regs tested
ble.s @rdfwd1 ;no, read next
bra.s @passrd ;must have passed
@failrd ;
move.b #16,d0 ;shift val
move.b d1,d6 ;get register offset
asl.l d0,d6 ;adjust it to upper word
move.b -(a1),d6 ;get write val
asl.w #8,d6 ;adjust it to msb of low word
move.b d3,d6 ;and finally the value read from map ram
@passrd ;
jmp (a3) ;rtn from routine with status
;laguna mapper ram test tables
;data patterns
MapTestTable
dc.b %00000111
dc.b %00000000
dc.b %00000001
dc.b %00000010
dc.b %00000100
dc.b %00000110
dc.b %00000101
dc.b %00000011
maptesttablesize
dc.w *-MapTestTable-1
MapTestTab2
dc.b 0
dc.b 1
dc.b 2
dc.b 3
dc.b 4
dc.b 5
dc.b 6
dc.b 7
dc.b 7
dc.b 6
dc.b 5
dc.b 4
dc.b 3
dc.b 2
dc.b 1
EndMapTestTab2
dc.b 0
ELSE
VramAddrTest ;these tests do not run on the machine
VramDataTest ;calling them
MapRamDataTest ;
MapRamUniqTest ;
moveq #-1,d6 ;load fail/no-log code
RTS6 ;return to caller
ENDIF ;(hasPowerMgr)
;---------------------------------------------------------------------------
;
; SetSCCIOPBypass
;
; This routine throws the SCC IOP into bypass mode.
;
; Called by BSR6
;
; Inputs: a3 - IOP SCC base address <1.3>
; Outputs: SR - Z-flag set if no errors
; Destroys: d0-d1,a0-a1
;---------------------------------------------------------------------------
SetSCCIOPBypass
move.b #resetIopRun,iopStatCtl(a3) ; init the Status/Ctl reg, hold IOP reset
; Download the IOP code
lea SCCIOPInitCode,a0 ; a0 <- start of IOP code (in this ROM)
movea.l a0,a1 ; keep copy in a1 for verify
move.w (a0)+,d0 ; get the size code (-1 for DBRA)
move.w (a0)+,iopRamAddr(a3) ; setup the code load address
@LoadLoop
move.b (a0)+,iopRamData(a3) ; download a byte
dbra d0,@LoadLoop ; load all of the bytes
; Verify the IOP code
move.w (a1)+,d0 ; get the size code (-1 for DBRA)
move.w (a1)+,iopRamAddr(a3) ; setup the code load address
@cmpLoop
move.b iopRamData(a3),d1 ; read byte from iop
cmp.b (a1)+,d1 ; compare to actual value
bne.s @initError ; doesn't match, exit
dbra d0,@cmpLoop ; load all of the bytes
; Start IOP execution
move.b #setIopRun,iopStatCtl(a3) ; release IOP reset (let it rip!)
lsr.w #6,d0 ; $FFFF -> $03FF -> loop 1024 times
@wait dbra d0,@wait ; delay a bit while IOP initializes
@InitError
add.w #1,d0 ; d0 = 0 if everything OK
RTS6 ; return to caller
;----------------------------------------------------------------------------
; 6502 code to throw SCC IOP into bypass mode
SCCIOPInitCode
dc.w (@end-@Start)-1 ; (byte) size of the code
dc.w $8000-(@end-@Start) ; (word) load address
@start ; code starts here
dc.b $A9,$81 ; 7FEE: lda #1*DEBUG+0*SCCISM+1*BYPASS
dc.b $8D,$30,$F0 ; 7FF0: sta SCCControlReg
dc.b $A9,$44 ; 7FF3: lda #SccIOCtlReg
dc.b $8D,$31,$F0 ; 7FF5: sta IOControlReg
dc.b $80,$FE ; 7FF8: bra $7FF8
dc.b $EE,$7F ; 7FFA 7FEE Non-Maskable Interrupt vector
dc.b $EE,$7F ; 7FFA 7FEE Processor reset vector
dc.b $EE,$7F ; 7FFA 7FEE Interrupt Request vector
@end ; code ends here
;;;------------------------------------------
;;;------------------------------------------
;;; these are utility subroutines used by
;;; the SCC tests
;;;------------------------------------------
;;;------------------------------------------
;----------------------------------------------------------
; GetSCCVIABases:
;
; Inputs: a0 - ptr to table of hardware base addresses
; d0 - bit mask indicating which base addresses are valid
; d2 - boxflag/decoder type
;
; Outputs: a2 - VIA1 base address
; a3 - SCC read base address (channel A)
; d3 - SCC write base offset
;----------------------------------------------------------
WITH DecoderInfo ;<21>
GetSCCVIABases ;
move.l VIA1Addr(a0),a2 ;get VIA1 base address
btst.l #SCCIOPExists,d0 ;do we have an iop scc?
beq.s @noIOP
move.l SCCIOPAddr(a0),a3 ;get iop scc base address
moveq.l #0,d3 ;write base offset is 0
bra.s @cont
@noIOP move.l SCCRdAddr(a0),a3 ;get scc read base
move.l SCCWrAddr(a0),d3 ;get scc write base
sub.l a3,d3 ;calculate write reg offset
@cont
bclr #3,VBufA(a2) ;bit low => gate C3M to SCC clock input
bset #3,VDirA(a2) ;make sure sync bit DDRA is output
addq #actl,a3 ;point to ch A
rts ;
ENDWITH ;<21>
;----------------------------------------------------------
; Restore: restores the scc to its normal system state
;
; a2 - VIA1 base address
; a3 - SCC read base address Ch A
; d3 - SCC write base offset Ch A
;----------------------------------------------------------
Restore ;
lea ResetTbl,a0 ;
bsr.s writescc ; Reset SCC
lea DefaultTbl,a0 ;
bsr.s writescc ; Restore channel A
subq #actl,a3 ;
lea DefaultTbl,a0 ; Restore channel B
bsr.s writescc ;
rts ;
;----------------------------------------------------------
; subroutine to set up the scc with data from scctable
; a0 - pointer to count and data table
; a2 - VIA1 base address
; a3 - SCC read base address (chB or chA)
; d3 - SCC write base offset
;----------------------------------------------------------
writescc ;
move.w (a0)+,d0 ;get table entry count, point to data
move.b (a3),d2 ;sync up the scc
@loop move (sp),(sp) ;delay
move.b (a0)+,(a3,d3.l) ;write an scc register
dbra d0,@loop ;again
rts ;
;-----------------------------------------------------------
;
; subroutine to test the scc in loopback mode
;
; a2 - VIA1 base address
; a3 - SCC read base address (chB or chA)
; d1 - write data/loop counter
; d2 - read data
; d3 - SCC write base offset
; d4 - timeout counter
; d6 - step number (<> 0 = error)
;-----------------------------------------------------------
scclp ;
move.w #1000,d0 ;allow 2 ms to clear any garbage chars
@10 tst.b (a2) ;access VIA (1uS)
dbra d0,@10 ;
tst.b sccdata(a3) ;clear any pending data
move #$80,d1 ;init test data = $80 <1.4>
; get xmit buffer empty
scclp1 moveq #-1,d4 ;timeout count
moveq #0,d6 ;clear step register
move.b #$30,(a3,d3.l) ;reset any error flags
move.b (sp),(sp) ;delay
@waitE btst #TXBE,(a3) ;transmit buffer empty?
bne.s sccout ;yes, continue
dbra d4,@waitE ;no, wait till empty or timeout
moveq #1,d6 ;error code: 1 = no 'TxBE' status
bra.s scclxit ;exit error
sccout move.b d1,sccdata(a3,d3.l) ;write data byte
moveq #-1,d4 ;timeout count
@waitT move.b #1,(a3,d3.l) ;see if character sent out
move (sp),(sp) ;delay
btst #0,(a3) ;character go out?
bne.s chkrda ;yes, wait for RDA
dbra d4,@waitT ;no, wait till it does or timeout
moveq #2,d6 ;step 2 = no 'all sent' status
bra.s scclxit ;
chkrda move #-1,d4 ;timeout count
@waitR btst #RXBF,(a3) ;receive buffer full?
bne.s sccin ;yes, see if character matched
dbra d4,@waitR ;no, wait till full or timeout
moveq #3,d6 ;step 3 = no 'Rcv Data Avail' status
bra.s scclxit ;
sccin move.b sccdata(a3),d2 ;read data
cmp.b d1,d2 ;did character match?
beq.s @check ;yes, make sure no rcv errors...
moveq #4,d6 ;step 4 = data compare error
bra.s scclxit ;exit
@check move.b #1,(a3,d3.l) ;select read reg 1
move (sp),(sp) ;delay
move.b (a3),d2 ;read it
andi.b #$70,d2 ;check for framing,parity,overrun
beq.s @next ;none, do next byte pattern
moveq #5,d6 ;step 5 = framing, parity, or overrun
bra.s scclxit ;
@next lsr.b #1,d1 ;walk 1 through byte <1.4>
bne scclp1 ;repeat until 0
scclxit
rts ;
;----------------------------------------------------------
; #85: SCCLoopTest tests the scc in internal loopback mode
; (assumes stack is operational (probably pointing to video ram))
;
; Inputs: a0 - ptr to table of hardware base addresses
; d0 - bit mask indicating which base addresses are valid
; d2 - boxflag/decoder type
; Uses:
; a0 - scc table pointer
; a2 - VIA1 base address
; a3 - SCC read base address (ch A or B)
; a6 - return address
;
; d0 - scratch
; d1 - scratch
; d2 - scratch
; d3 - SCC write base offset
; d6 - step number (error code)
;----------------------------------------------------------
SCCLoopTest ;
IF forRomulator THEN ; <T7>
TestInRAM a2 ;are we running in RAM? <T7>
beq.s @DoTest ;perform the test not <T7>
moveq.l #-2,d6 ;else, report something unique <T7>
RTS6 ;and return <T7>
@DoTest ; <T7>
ENDIF
move.w sr,-(sp) ;
ori.w #hiIntMask,sr ;turn ints off
movec.l cacr,d3 ;get the cacr register value <T10>
move.l d3,-(sp) ;save it <T10>
bclr.l #CACR_IE_040,d3 ;disable the '040 instruction cache (no affect <T10>
movec.l d3,cacr ;on '030s because this bit doesn't exist) <T10>
bsr GetSCCVIABases ;get SCC Ch-A and VIA base addresses
; now do a loopback test on channel A
lea MainTbl,a0 ;scc data tables pointer
bsr writescc ;set up channel A
lea LoopTbl,a0 ;set internal loopback mode
bsr writescc ;
bsr scclp ;execute the loop test
bne.s @ExitTest ;exit scc test
; now do a loopback test on channel B
bsr.s writescc ;
lea MainTbl,a0 ;scc data tables pointer
bsr writescc ;set up channel B
lea LoopTbl,a0 ;set internal loopback mode
bsr writescc ;
bsr scclp ;execute the loop test
addq #actl,a3 ;adjust offset back to channel A
beq.s @ExitTest ;exit scc test
add.w #$10,d6 ;bump step counter for ch B
@ExitTest ;
bsr Restore ;get SCC back to normal mode
move.l (sp)+,d3 ;retrieve the cacr <T10>
movec.l d3,cacr ;and restore it <T10>
move.w (sp)+,sr ;restore sr
RTS6 ;return to caller
;-----------------------------------------------------------
;
; regloop performs a write/read test on the R/W scc registers
;
; a2 - VIA1 base address
; a3 - SCC read base address (+Actl)
; d3 - SCC write base offset
;
; d0 - work
; d1 - iteration count
; d2 - register under test
; d4 - R/W data
; d5 - bit mask for register bits that are not R/W (reg 15)
; d6 - 0 - if success, else
;
; FFrreeaa - if error, where:
;
; rr - register under test
; ee - expected value to be read
; aa - actual value read
;
;-----------------------------------------------------------
regLoop ;
moveq.l #0,d6 ;flag no errors
move.w #$FF,d1 ;iteration count
moveq.l #0,d4 ;data pattern
move.b (a3),d0 ;sync up scc
move.l (sp),(sp) ;delay
move.b d2,(a3,d3.l) ;select reg
move.l (sp),(sp) ;delay
move.b (a3),-(sp) ;save register's initial value
move.l (sp),(sp) ;delay
@Loop move.b d2,(a3,d3.l) ;select register to be tested
move.l (sp),(sp) ;delay
and.b d5,d4 ;mask off any non R/W bits
move.b d4,(a3,d3.l) ;write data
move.l (sp),(sp) ;delay
move.b d2,(a3,d3.l) ;select register under test
move.l (sp),(sp) ;delay
move.b (a3),d0 ;read data
and.b d5,d0 ;mask off any non R/W bits
cmp.b d4,d0 ;
bne.s @Fail ;compare error
addq.l #1,d4 ;bump pattern
dbra.w d1,@Loop ;continue test
bra.s @Pass ;done, exit test
@Fail move.b #$FF,d6 ;error, FF in high byte
asl.l #8,d6
move.b d2,d6 ;register number in next byte
asl.l #8,d6
move.b d4,d6 ;masked expected value next
asl.l #8,d6
move.b d0,d6 ;actual value in lsb
@Pass move.b d2,(a3,d3.l) ;select reg
move.l (sp),(sp) ;delay
move.b (sp)+,(a3,d3.l) ;restore reg initial value
tst.l d6 ;set cc's if error
rts ;
;-----------------------------------------------------------
;
; #84: SCCRegTest tests the only r/w registers in the scc which are
; the interrupt vector register (xr2) and the upper and
; lower time constant registers (xr12-13) and the interrupt
; mode register (xr15). Both channels A and B are tested.
; (Assumes power is already on to SCC.)
; (Assumes operational stack (video ram))
;
;
; a2 - VIA1 base address
; a3 - SCC read base address (+Actl)
; a4 - table pointer
; a6 - return address
; d1 - scratch
; d2 - register under test
; d3 - SCC write base offset
; d5 - bit mask
; d6 - error flag
;----------------------------------------------------------
SCCRegTest ;
IF forRomulator THEN ; <T7>
TestInRAM a2 ;are we running in RAM? <T7>
beq.s @DoTest ;perform the test not <T7>
moveq.l #-2,d6 ;else, report something unique <T7>
RTS6 ;and return <T7>
@DoTest ; <T7>
ENDIF
bsr GetSCCVIABases ;get SCC Ch-A and VIA base addresses
lea ResetTbl,a0 ;
bsr.s writescc ; Reset SCC
lea regtests,a4 ;register test table
@loopA move.b (a4)+,d2 ;register under test
bmi.s @chB ;done with ch A
move.b (a4)+,d5 ;bit mask
bsr.s regloop ;
beq.s @loopA ;
bra.s @regAXit ;error
@chB subq #actl,a3 ;point to ch B
lea bregtests,a4 ;
@loopB move.b (a4)+,d2 ;register under test
bmi.s @regBXit ;not done
move.b (a4)+,d5 ;bit mask
bsr.s regloop ;
beq.s @loopB ;
@regBXit
addq #actl,a3 ;point to ch A
@regAXit
bsr restore ;restore scc to normal
RTS6 ;return to caller
;-----------------------------------------------------------
; DisableInts: disables interrupts at the chip (VIA,OSS,RBV)
;
; Inputs: a0 - points to table of hardware base addresses
; d0 - bits indicating which base address are valid
;
; Outputs: none
;
; Destroys: a1,a2,d1
;-----------------------------------------------------------
WITH DecoderInfo ;<21>
DisableInts ; <1.5>
movea.l (sp)+,a1 ;get return address
ori.w #hiIntMask,sr ;mask out interrupts at 68xxx
btst.l #OSSExists,d0 ;do we have an OSS?
beq.s @via2 ;no, see if we have a via2
movea.l OSSAddr(a0),a2 ;yes, get OSS base
moveq #OSSMskLast,d1 ;prepare to blast all int masks
@loop move.b (a2,d1.w),-(sp) ;save old mask level
clr.b (a2,d1.w) ;set mask level to 0 (no interrupt)
dbra d1,@loop
@via2
moveq #$7F,d1 ; all interrupts disabled - gets used a bit <H19><SM6>
btst.l #Via2Exists,d0
beq.s @rbv ;no, see if we have an RBV
movea.l VIA2Addr(a0),a2 ;point to VIA2 base
move.b VIER(a2),-(sp) ;save old value
move.b d1,VIER(a2) ;turn off VIA2 interrupts <H19><SM6>
@rbv
btst.l #RBVExists,d0
beq.s @exit
movea.l RBVAddr(a0),a2 ;point to RBV base
move.b RvSEnb(a2),-(sp) ; save slot interrupt enables, <H19><SM6>
bset #ifIRQ,(sp) ; make sure the "any IRQ" bit is set, <H19><SM6>
move.b d1,RvSEnb(a2) ; and disable them <H19><SM6>
move.b RvIER(a2),-(sp) ;save other interrupt enables
bset #ifIRQ,(sp) ; make sure the "any IRQ" bit is set, <H19><SM6>
move.b d1,RvIER(a2) ;turn off RBV interrupts
@exit
movea.l VIA1Addr(a0),a2 ;point to VIA1 base <1.9>
move.b VIER(a2),-(sp) ;save old value
move.b d1,VIER(a2) ;turn off VIA1 interrupts <H19><SM6>
jmp (a1) ; exit
ENDWITH ;<21>
;-----------------------------------------------------------
; RestoreInts: restores interrupts at the chip (VIA,OSS,RBV)
;
; Inputs: a0 - points to table of hardware base addresses
; d0 - bits indicating which base address are valid
;
; Outputs: none
;
; Destroys: a1,a2,d1
;-----------------------------------------------------------
RestoreInts ; <1.5>
movea.l (sp)+,a1 ;get return address
moveq #$7F,d1 ; all interrupts disabled - gets used a bit <H19><SM6>
movea.l DecoderInfo.VIA1Addr(a0),a2 ;point to VIA1 base <21><1.9><SM6>
move.b d1,VIER(a2) ;turn off VIA1 interrupts <H19><SM6>
move.b (sp)+,VIER(a2) ;turn on original values
btst.l #DecoderInfo.RBVExists,d0 ; <21>
beq.s @via2
movea.l DecoderInfo.RBVAddr(a0),a2 ;point to RBV base <21>
move.b (sp)+,RvIER(a2) ;restore RBV interrupts
move.b (sp)+,RvSEnb(a2) ;restore RBV slot interrupts <H19><SM6>
@via2
btst.l #DecoderInfo.Via2Exists,d0 ; <21>
beq.s @oss ;no, see if we have an RBV
movea.l DecoderInfo.VIA2Addr(a0),a2 ;point to VIA2 base <21>
move.b d1,VIER(a2) ;turn off VIA2 interrupts <H19><SM6>
move.b (sp)+,VIER(a2) ;restore VIA2 interrupts
@oss
btst.l #DecoderInfo.OSSExists,d0 ;do we have an OSS? <21>
beq.s @exit ;no, restore via1 ints and exit
movea.l DecoderInfo.OSSAddr(a0),a2 ;yes, get OSS base <21>
moveq #0,d1 ;
@loop move.b (sp)+,(a2,d1.w) ;restore mask level
addq.b #1,d1
cmpi.b #OSSMskLast,d1 ;restored all masks?
ble.s @loop ;no, continue
@exit
jmp (a1) ; exit
;-----------------------------------------------------------
; #86: SCCTimerTest verifies that the scc timer zero count interrupts
; the host MPU.
;
; Inputs: a0 - points to table of hardware base addresses
; d0 - bits indicating which base address are valid
;
; Outputs: d6 - error code, -1 if test not applicable
;
; Destroys: d0-d5,a0-a4,a5
;-----------------------------------------------------------
SCCTimerTest ;
IF forRomulator THEN ; <T7>
TestInRAM a2 ;are we running in RAM? <T7>
beq.s @DoTest ;perform the test not <T7>
moveq.l #-2,d6 ;else, report something unique <T7>
RTS6 ;and return <T7>
@DoTest ; <T7>
ENDIF
bsr GetSCCVIABases ;get SCC Ch-A and VIA base addresses
bsr DisableInts ;turn off interrupt sources at the chips <1.5>
move.l d0,-(sp) ;save bases valid bits
move.l a0,-(sp) ;save ptr to table of base addresses
btst.l #DecoderInfo.OSSExists,d0 ;do we have an OSS? <21>
beq.s @vbr ;no, continue
movea.l DecoderInfo.OSSAddr(a0),a1 ;yes, get OSS base <21>
move.b #MskIOP0,OSSMskPScc(a1) ;enable SCC to OSS, ints masked at CPU
@vbr
movec VBR,a5 ;
add.l #autoint4,a5 ;point to level 4 vector
move.l (a5),-(sp) ;preserve vector
lea LocalSCCInt,a1 ;set up local interrupt vector
move.l a1,(a5) ;
lea TimerTbl,a0 ;Setup SCC, baud const=FFFF, int on 0 count
bsr writescc ;
; interrupts are initialized
moveq #1,d6 ;step 1
moveq #-1,d1 ;interrupt flag
move.l #$50000,d0 ;wait count
move.w #$2300,sr ;allow scc ints
@1 tst d1 ;wait for first int to sync up
beq.s @2 ;
subq.l #1,d0 ;wait
bne.s @1 ;
bra.s intexit ;error, no zero count int
@2 tst d1 ;second int came?
bne.s intdone ;done
subq.l #1,d0 ;
bne.s @2 ;
@3 moveq #2,d6 ;error code: 2 = no zero count int
bra.s intexit ;exit test
; interrupt received, verify correct timimg
intdone ori.w #hiIntMask,sr ;turn ints off
sub.l d2,d5 ;how many counts?
moveq #3,d6 ;in case error
cmp.l #$10000,d5 ;check upper limit
bgt.s intexit ;too slow timer
moveq #4,d6 ;in case error
cmp.l #$100,d5 ;check lower limit
blt.s intexit ;too fast timer
moveq #0,d6 ;no error
; now restore the world for exit
intexit lea ResetTbl,a0 ;hardware reset
bsr.s writescc ;
ori.w #hiIntMask,sr ;turn ints off
movec VBR,a5 ;
add.l #autoint4,a5 ;point to level 4 vector
move.l (sp)+,(a5) ;restore vector
move.l (sp)+,a0 ;restore ptr to table of base addresses
move.l (sp)+,d0 ;restore bases valid bits
bsr RestoreInts ;restore interrupts at chips
RTS6 ;return to caller
;-----------------------------------------------------------
; LocalSCCInt is the local interrupt handler for scc zero count
;-----------------------------------------------------------
LocalSCCInt ;
move.b #$10,(a3,d3.l) ;reset ext status int, Channel A or B
move.l d0,d2 ;get counter
tst d1 ;is first interrupt?
bpl.s @1 ;no
move.l d2,d5 ;first time, save counter
@1 addq #1,d1 ;bump interrupt flag
tst.b VIER(a2) ;read via register
tst.b VIFR(a2) ;sync to via clock (delay)
rte ;
;-----------------------------------------------------------
;
; scc init tables
;
;-----------------------------------------------------------
MainTbl
DC.W ResetTbl-MainTbl-3 ;byte count - 1
DC.B 9,$C0 ;hardware reset
DC.B 4,$4C ;x16 clk, 2 stop bits, no parity
DC.B 11,$50 ;BR gen clk to rcv, xmit
DC.B 15,00 ;free dcd
DC.B 12,00 ;fast baud
DC.B 13,00 ;
DC.B 14,$01 ;enable BR gen
DC.B 3,$C1 ;8 bits/char rcv, enable rcvr
DC.B 5,$6A ;8 bits/char xmit, enable xmtr
ResetTbl
DC.W DefaultTbl-ResetTbl-3 ;
DC.B 9,$C0 ;hardware reset
DefaultTbl
DC.W LoopTbl-DefaultTbl-3 ;
DC.B 15,$08 ;enable DCD ints
DC.B 0,$10 ;reset ext status int
DC.B 1,$01 ;enable ext status ints
DC.B 9,$08 ;master interrupt enable
LoopTbl
DC.W TimerTbl-LoopTbl-3 ;
DC.B 14,$11 ;enable BR gen and internal loopback
DC.B 5,$68 ;8 bits/char xmit, enable xmtr, disable RTS
TimerTbl
DC.W endTbl-TimerTbl-3 ;
DC.B 9,$C0 ;hardware reset
DC.B 12,$FF ;BR gen counter = $FFFF
DC.B 13,$FF ;
DC.B 14,$00 ;
DC.B 14,$03 ;enable BR timer
DC.B 15,$02 ;zero count interrupt enable
DC.B 0,$10 ;reset ext status int
DC.B 1,$01 ;enable external status int
DC.B 9,$0A ;master interrupt enable, no vector
endTbl EQU * ;
regtests
DC.B 2,$FF ;register test: reg #, bit mask
DC.B 12,$FF ;
DC.B 13,$FF ;
DC.B 15,$FA ;
DC.B $FF,$FF ;
bregtests
DC.B 2,$00 ;register test: reg #, bit mask
DC.B 12,$FF ;reg 2 is modified by status info
DC.B 13,$FF ;on channel B
DC.B 15,$FA ;
DC.B $FF,$FF ;
;---------------------------------------------------------------------------------
; #87: VIATest tests the VIA IRQ and timer function by setting up the T1 and T2 timer
; and CA1 interrupts, then looking for them to come through.
;
; Inputs: a0 - points to table of hardware base addresses
; d0 - bits indicating which base address are valid
;
; Outputs: d6 - error code, -1 if test not applicable
;
; Destroys: d0,d1,d3,d4,d5,a1-a3
;
; Called by BSR6
;----------------------------------------------------------------------------------
VIATest ;
bsr DisableInts ;turn off interrupt sources at the chips <1.5>
btst.l #DecoderInfo.OSSExists,d0 ;do we have an OSS? <21>
beq.s @vbr ;no, continue
movea.l DecoderInfo.OSSAddr(a0),a1 ;yes, get OSS base <21>
move.b #MskVIA1,OSSMskVia1(a1) ;enable VIA1 to OSS, ints masked at VIA
move.b #Msk60Hz,OSSMsk60Hz(a1) ;enable 60hz to OSS, ints masked at 68030
@vbr
movec VBR,a2 ;
add.l #autoint1,a2 ;point to level 1 vector
move.l (a2),-(sp) ;preserve os level 1 vector
lea LocalVIA1Int,a3 ;get local interrupt vector
move.l a3,(a2) ;and install it
moveq #0,d6 ;init step reg
; First test T1 continuous and T2 one shot function, along with CA1 (vsync)
move.l d0,d1 ;keep bases valid flags in d1
movea.l DecoderInfo.VIA1Addr(a0),a2 ;point to VIA1 base <21>
and.b #$1F,VACR(a2) ;select timed interrupt (one shot)
or.b #$40,VACR(a2) ;select continuous interrupt on T1
move.b #$62,VIFR(a2) ;clear any pending CA1, T1, T2 ints
move.b #$E2,VIER(a2) ;enable T1, T2, CA1 interrupts
moveq #0,d3 ;init CA1 counter
moveq #0,d4 ;init T1 counter
moveq #0,d5 ;init T2 counter
; load the counters
move.b #$FF,Vt1CH(a2) ;preload uppers <20>
move.b #$FF,Vt2CH(a2) ;preload uppers <20>
move.b #$FF,Vt1C(a2) ;load T1 low
move.b #$FF,Vt2C(a2) ;load T2 low
move.b #$02,Vt1CH(a2) ;start T1 for small count
move.b #$3F,Vt2CH(a2) ;start T2 at quarter count
move.l #$000F0000,d0 ;timeout value
move.w #$2000,sr ;allow interrupts
@10 cmp.w #10,d3 ;wait for 10 CA1s to come through
beq.s @20 ;done...
subq.l #1,d0 ;count a loop
bne.s @10 ;until either either 10 CA1s come through or timeout
@20 ori.w #hiIntMask,sr ;turn ints off
moveq #1,d6 ;step 1 = checking for CA1
tst.w d3 ;check for any CA1 int
beq Int1Exit ;none, exit with error
moveq #2,d6 ;step 2 = check for correct CA1 count
cmp.w #10,d3 ;check for 10 CA1s
bne Int1Exit ;wrong count, exit with error
moveq #3,d6 ;step 3 = check for any T1s
tst.w d4 ;check for any T1s
beq Int1Exit ;none, exit with error
moveq #4,d6 ;step 4 = check for min number of T1s
cmp.w #$80,d4 ;expecting > $7F T1s
bmi Int1Exit ;too low
moveq #5,d6 ;step 5 = check for max number of T1s
cmp.w #$D0,d4 ;expecting < $D0 T1s
bpl Int1Exit ;too high
moveq #6,d6 ;step 6 = check for any T2
tst.w d5 ;check for any T2
beq Int1Exit ;none, exit with error
moveq #7,d6 ;step 7 = check for correct T2 count
cmp.w #1,d5 ;expecting only 1 T2
bne Int1Exit ;wrong count, exit with error
moveq #8,d6 ;step 8 = verify that T1 continued downcounting
moveq #-1,d0 ;timeout value
@25 tst.b VT1C(a2) ;read out T1 low
dbne d0,@25 ;until it decrements from 0 or timeout
beq Int1Exit ;still 0, exit with error
moveq #9,d6 ;step 9 = verify that T2 continued downcounting
moveq #-1,d0 ;timeout value
@27 tst.b VT2C(a2) ;read out T2 low
dbne d0,@27 ;until it decrements from 0 or timeout
beq.w Int1Exit ;still 0, exit with error
; ok, now test the one shot interrupt function of T1
and.b #$1F,VACR(a2) ;select one shot interrupt on T1
move.b #(1<<ifCA1|1<<ifT1|1<<ifT2),VIFR(a2) ;clear any pending CA1, T1, T2 ints
move.b #$E2,VIER(a2) ;enable CA1, T1, T2 interrupts
moveq #0,d3 ;init CA1 counter
moveq #0,d4 ;init T1 counter
moveq #0,d5 ;init T2 counter
move.b #$FF,Vt1CH(a2) ;preload uppers <20>
move.b #$FF,Vt2CH(a2) ;preload uppers <20>
move.b #$FF,Vt1C(a2) ;load T1 low
move.b #$FF,Vt2C(a2) ;load T2 low
move.b #$04,Vt1CH(a2) ;start T1 for small count
move.b #$1F,Vt2CH(a2) ;start T2 at eighth count
move.l #$000F0000,d0 ;timeout value
move.w #$2000,sr ;allow interrupts
@30 cmp.w #10,d3 ;wait for 10 CA1s to come through
beq.s @40 ;done...
subq.l #1,d0 ;count a loop
bne.s @30 ;until either either 10 CA1s come through or timeout
@40 ori.w #hiIntMask,sr ;turn ints off
moveq #10,d6 ;step 10 = checking for CA1
tst.w d3 ;check for any CA1 int
beq.s Int1Exit ;none, exit with error
moveq #11,d6 ;step 11 = check for any T1
tst.w d4 ;check for any T1
beq.s Int1Exit ;none, exit with error
moveq #12,d6 ;step 12 = check for correct number of T1s
cmp.w #1,d4 ;expecting only 1 T1
bne.s Int1Exit ;wrong count, exit with error
moveq #13,d6 ;step 13 = check for any T2
tst.w d5 ;check for any T2
beq.s Int1Exit ;none, exit with error
moveq #14,d6 ;step 14 = check for correct number of T2s
cmp.w #1,d5 ;expecting only 1 T2
bne.s Int1Exit ;wrong count, exit with error
moveq #15,d6 ;step 15 = verify that T2 continued downcounting
moveq #-1,d0 ;timeout value
@45 tst.b VT2C(a2) ;read out T2 low
dbne d0,@45 ;until it decrements from 0 or timeout
beq.s Int1Exit ;still 0, exit with error
clr.w d6 ;no errors
Int1Exit ;
and.b #$1F,VACR(a2) ;select timed interrupt (one shot)
ori.w #hiIntMask,sr ;turn ints off
movec VBR,a2 ;
add.l #autoint1,a2 ;point to level 1 vector
move.l (sp)+,(a2) ;restore os level 1 vector
move.l d1,d0 ;get bases valid bits back in d0
bsr RestoreInts ;restore interrupts at the chips
RTS6 ;return to caller
;---------------------------------------------------------------------------
; Interrupt handler
;
; Inputs: a1 - ptr to OSS base (if it exists)
; d1 - bases valid flags
;
; Outputs: d3 - bumped if VBL interrupt
; d4 - bumped if Timer1 interrupt
; d5 - bumped if Timer2 interrupt
;
; Destroys: a1,d2
;---------------------------------------------------------------------------
LocalVIA1Int
move.l d0,-(sp) ;save d0
move.b VIFR(a2),d0 ;read IFR flags
andi.b #(1<<ifCA1 | 1<<ifT1 | 1<<ifT2),d0;just look at timer and CA1 flags
move.b d0,VIFR(a2) ;clear them
btst.l #DecoderInfo.OSSExists,d1 ;do we have an OSS? <21>
beq.s @noOSS ;no, check VIA interrupts
move.w OSSIntStat(a1),d2 ;see who is interrupting
btst #OSSIntVBL60Hz,d2 ;see if 60Hz pseudo VBL interrupt
beq.s @timer1 ;no, see if timer
move.b #0,OSS60HzAck(a1) ;clear vbl
bra.s @vbl ;and count it
@noOSS btst #ifCA1,d0 ;check for CA1
beq.s @timer1 ;none
@vbl addq #1,d3 ;count a CA1 interrupt
@timer1 btst #ifT1,d0 ;check for T1
beq.s @timer2 ;none
addq #1,d4 ;count a T1 int
@timer2 btst #ifT2,d0 ;check for T2
beq.s @exit ;none
addq #1,d5 ;count a T2 int
@exit move.l (sp)+,d0 ;restore d0
rte ;
;-------------------------------------------------------------------------------
;
; #88: SCSI chip status lines test
;
; Inputs: a0 - points to table of hardware base addresses
; d0 - bits indicating which base address are valid
; d2.lw - boxflag/decoder type
; d2.hw - private feature flags
;
; Outputs: d6 - error code, -1 if test not applicable
;
; Destroys: ?
;
; Called by BSR6
;-------------------------------------------------------------------------------
;
TestSCSI ;
btst #DecoderInfo.SCSIExists,d0 ;do we really have a SCSI chip? <21>
beq @noSCSI ;yes, test it
movea.l DecoderInfo.VIA1Addr(a0),a2 ;point to VIA1 base <21>
movea.l DecoderInfo.SCSIAddr(a0),a0 ;point to scsi (read base) <21>
move.l a0,a1 ;set up write base
add.l #wrOffs,a1 ;calculate write base
move.b #$80,sICR(a1) ;assert reset <13>
moveq #0,d0 ;get a zero
move.b d0,sICR(a1) ;deassert reset <13>
tst.b sRESET(a0) ;clear pending interrupt bit <13>
moveq #1,d6 ;increment step register
move.b #$80,sICR(a1) ;assert reset <13>
move.b sICR(a0),d1 ;read back <13>
cmp.b #$80,d1 ;see if ok
bne @TestExit ;error, exit
addq #1,d6 ;increment step register
move.b sCSR(a0),d1 ;read status reg <13>
and.b #$80,d1 ;just the bit we're testing
cmp.b #$80,d1 ;see if ok
bne @TestExit ;error, exit
move.b #$0,sICR(a1) ;release reset <13>
addq #1,d6 ;increment step register
tst.b VIER(a2) ;read via register
tst.b VIFR(a2) ;sync to via clock (delay)
move.b #$10,sICR(a1) ;assert ack <13>
move.b sICR(a0),d1 ;read back <13>
cmp.b #$10,d1 ;see if ok
bne.s @TestExit ;error, exit
addq #1,d6 ;increment step register
move.b sBSR(a0),d1 ;read status reg <13>
and.b #$01,d1 ;just the bit we're testing
cmp.b #$01,d1 ;see if ok
bne.s @TestExit ;error, exit
addq #1,d6 ;increment step register
move.b #$08,sICR(a1) ;assert bsy <13>
move.b sICR(a0),d1 ;read back <13>
cmp.b #$08,d1 ;see if ok
bne.s @TestExit ;error, exit
addq #1,d6 ;increment step register
move.b sCSR(a0),d1 ;read status reg <13>
and.b #$40,d1 ;just the bit we're testing
cmp.b #$40,d1 ;see if ok
bne.s @TestExit ;error, exit
addq #1,d6 ;increment step register
move.b #$04,sICR(a1) ;assert sel <13>
move.b sICR(a0),d1 ;read back <13>
cmp.b #$04,d1 ;see if ok
bne.s @TestExit ;error, exit
addq #1,d6 ;increment step register
move.b sCSR(a0),d1 ;read status reg <13>
and.b #$02,d1 ;just the bit we're testing
cmp.b #$02,d1 ;see if ok
bne.s @TestExit ;error, exit
addq #1,d6 ;increment step register
move.b #$02,sICR(a1) ;assert atn <13>
move.b sICR(a0),d1 ;read back <13>
cmp.b #$02,d1 ;see if ok
bne.s @TestExit ;error, exit
addq #1,d6 ;increment step register
move.b sBSR(a0),d1 ;read status reg <13>
and.b #$02,d1 ;just the bit we're testing
cmp.b #$02,d1 ;see if ok
bne.s @TestExit ;error, exit
moveq #0,d6 ;clear step reg
@TestExit
RTS6 ;return to caller
@noSCSI
moveq #-1,d6 ;no, load fail/no-log code
RTS6 ;return to caller
TestASC ;
;-------------------------------------------------------------------------------
;
; #89: Apple Sound Chip test
; This is a test of the apple sound chip registers and FIFO RAM
; currently, it checks for either new or old versions of chip
; registers are tested for bit retention across all legal values
; register 6 is not tested because it makes noises when accessed
; (based on version 1.7 of SndTest.a)
;
; Inputs: a0 - points to table of hardware base addresses
; d0 - bits indicating which base address are valid
; d2.lw - boxflag/decoder type
; d2.hw - private feature flags
;
; Outputs: d6 - error code, -1 if test not applicable
; 0001xxxx if register test failed
; 0002xxxx if ASC FIFO RAM test failed
; 0003xxxx if Record FIFO RAM test failed
; Destroys: ?
;
; Called by BSR6
;-------------------------------------------------------------------------------
btst.l #DecoderInfo.ASCExists,d0 ;have an ASC? <21>
beq noASC ;no, exit
movem.l d0-d5/a0-a4,-(sp) ;ok to use a stack here:
move.w sr,-(sp) ;called by non-crit (after stk ram tested)
ori.w #hiIntMask,sr ;turn ints off
clr.l d6 ; clear error register
clr.l d5 ; clear 'actual value' register
clr.l d4 ; clear 'expected value' register
movea.l DecoderInfo.VIA1Addr(a0),a2 ;point to VIA1 base for quasi call<21>
movea.l DecoderInfo.ASCAddr(a0),a1 ;point to ASC base <21><8>
move.b ascVersion(a1),d3 ;Get the ASC version number <18>
and.b #$F0,d3 ;Mask off the sound type nibble <18>
cmp.b #elsieSound,d3 ;Is this an Elsie machine? <18>
bne.s @NotElsie ;Branch if not <18>
lea sndrnVISA,a4 ; get reg ptr for VISA chip test registers <8>
lea sndrdVISA,a3 ; get reg ptr for VISA chip test data <8>
bra.s @GoTest ;and go test the sound chip <18>
@NotElsie
move.b ascVersion(a1),d3 ;Get the ASC version number <H15><SM6>
cmp.b #batmanSound,d3 ;Is this a batman sound implementation? <18>
bne.s @NotOrigBatman ;Branch if not "original" Batman <H15><SM6>
lea sndrnBatman,a4 ;Get test register pointer for batman <18>
lea sndrdBatman,a3 ;and get the test data for batman <18>
bra.s @GoTest ;and go test that chip! <18>
@NotOrigBatman
and.b #$F0,d3 ; mask minor version to check for derivatives of Batman (Batrats) <H15><SM6>
cmp.b #batmanSound,d3 ;Is this a batman sound implementation? <H15><SM6>
bne.s @NotBatman ;Branch if not "original" Batman <H15><SM6>
lea sndrnBatRatsSonora,a4 ;Get test register pointer for Sonora-style batman <H15><SM6>
lea sndrdBatRatsSonora,a3 ;and get the test data <H15><SM6>
bra.s @GoTest ;and go test that chip! <H15><SM6>
@NotBatman
move.w d2,d3 ;get boxflag <18>
lsr.w #8,d3 ; <18>
cmpi.b #BoxMacIIsi,d3 ;is it a IIsi (Erickson)? <18><29>
bne.s @NotErickson ;Branch if not <18>
lea sndrnio,a4 ; get reg ptr for sound i/p test registers <7>
lea sndrdio,a3 ; get reg ptr for sound i/p test data <7>
bra.s @GoTest ;and go test the sound chip <18>
@NotErickson ;We have a standard ASC chip <18>
lea sndrnold,a4 ; get reg ptr for old sound chip test registers<8>
lea sndrdold,a3 ; get reg ptr for old sound chip test data <8>
move.b #$1c,ascVolControl(a1) ; write 1 to bits 2, 3, 4 of register 6 <17><8>
move.b ascVolControl(a1),d3 ; read contents of register 6 <17><8>
andi.b #$1c,d3 ; mask out everything except bits 2, 3, 4 <8>
bne.s @GoTest ; read ones, so we have older part
lea sndrnnew,a4 ; get reg ptr for new sound chip test registers
lea sndrdnew,a3 ; get reg ptr for new sound chip test data
bra.s @GoTest ;go test the ASC <18>
@NextReg
addq.l #2,a4 ;increment past the mask word <19>
@GoTest
move.l (a4)+,d3 ; get current register to test <19>
bmi.s @FIFO ; all done... go check FIFO RAM <19>
subq.w #1,d3 ;Adjust the count <19>
@loop swap d3 ;
move.b (a3)+,d4 ; get test data <7>
move.b d4,(a1,d3.w) ; stuff the test data <7>
tst.b (a2) ;delay a bit <7>
move.b (a1,d3.w),d5 ; read it back <7>
and.w (a4),d5 ;apply the mask <19>
swap d3 ;get ready for dbne <19>
cmp.b d4,d5 ; does written value match read value?
dbne.w d3,@loop ;loop until done <19>
beq.s @NextReg ;go to next reg if last cmp was OK <19>
; From here to the next <7> flag below was added to support sound in testing
swap d3 ;get the reg # into the low word again <19>
move.l #$10000,d6 ; no, set error # in upper word of d6
move.w d3,d6 ; set fail code to reg#
bra @exit ; and exit
; OK so far. Now test the Sound FIFO's, first with a decrementing pattern
; then an incrementing pattern
@FIFO cmp.b #DecoderKinds.VISADecoder,d2 ; have we the VISA implementation of the ASC regs<8><21>
beq @exit ; yes jump <8>
cmp.b #DecoderKinds.MSCDecoder,d2 ; <H16><SM6>
beq @exit ; skip this also <H16><SM6>
move.b ascVersion(a1),d3 ; get the ASC version <H15><SM6>
andi.b #$F0,d3 ; get the upper nibble <H15><SM6>
cmp.b #batmanSound,d3 ; is this a batman? <H15><SM6>
beq.w @exit ; exit now if it is <H15><SM6>
move.b #$2,ascMode(a1) ; set mode to waveform <17>
move.b #$0,ascPlayRecA(a1) ; ensure play mode <18>
move.b #0,ascVolControl(a1) ; volume = 0 <17>
move.b #$00,d5 ; set test pattern mask <8>
@11 move.w #$7ff,d4 ; set loop count for 2k
movea.l a1,a2
@12 move.b d5,d3 ; <8>
eor.b d4,d3 ; <8>
move.b d3,(a2)+ ; write out pattern <8>
dbra d4,@12
movea.l a1,a2 ; now check if written ok
move.w #$7ff,d4 ; set loop count for 2k
@13 move.b d5,d3 ; <8>
eor.b d4,d3 ; <8>
move.b (a2)+,d1 ; <8>
cmp.b d3,d1
bne.s @14
dbra d4,@13
cmp.b #$ff,d5 ; both patterns tested <8>
beq.s @sndin
move.b #$ff,d5 ; do second pattern <8>
bra.s @11
@14 move.l #$20000,d6 ; flag error type in upper word of d6
move.w a2,d6 ; failing address +1
and.w #$07ff,d6
bra @exit
@sndin move.w d2,d3 ; get boxflag
lsr.w #8,d3 ;
cmpi.b #BoxMacIIsi,d3 ; is it a IIsi (Erickson)? <29>
bne.s @exit ; no, we're finished
move.b ascVersion(a1),d3 ;get the ASC version <18>
andi.b #$F0,d3 ;get the upper nibble <18>
cmp.b #batmanSound,d3 ;is this a batman? <18>
beq.s @exit ;exit now if it is <18>
move.b #$81,ascPlayRecA(a1) ; set RFD and Record mode <18>
move.b #$80,ascFifoControl(a1) ; reset the FIFO ptr <17>
move.b #0,ascFifoControl(a1) ; <17>
move.b #$00,d5 ; first test loop (decrementing pattern) <8>
@21 move.w #$3ff,d4 ; set loop count for 1k
move.l a1,a2
@22 move.b d5,d3 ; <8>
eor.b d4,d3 ; <8>
move.b d3,(a2)+ ; write out pattern to Record FIFO <8>
dbra d4,@22
move.l a1,a2 ; now check if written ok
move.w #$3ff,d4 ; set loop count for 1k
@23 move.b d5,d3 ; <8>
eor.b d4,d3 ; <8>
move.b (a2)+,d1 ; <8>
cmp.b d3,d1
bne.s @25
dbra d4,@23
cmp.b #$ff,d5 ; both loops tested <8>
beq.s @exit ; yes jump
move.b #$ff,d5 ; test pattern <8>
bra.s @21 ; go test Record FIFO with second pattern (incrementing pattern)<8>
@25 move.l #$30000,d6 ; flag error type in upper word of d6
move.w a2,d6 ; failing address +1
and.w #$03ff,d6
@exit bsr.s snd_reg_init ; re-initialize the device
btst.l #DecoderInfo.VIA2Exists,d0 ; see if we have VIA2 <21>
beq.s @VIA2done ; if not, skip it
movea.l DecoderInfo.VIA2Addr(a0),a2 ; get VIA2 base address <21>
or.b #$90,vIER(a2) ; Clear sound interrupt flag.
@VIA2done
btst.l #DecoderInfo.RBVExists,d0 ; see if we have an RBV <21>
beq.s @RBVdone ; if not, skip it
movea.l DecoderInfo.RBVAddr(a0),a2 ; get RBV base address <21>
or.b #$90,RvIFR(a2) ; clear sound interrupt flag
@RBVdone
; From here to the next <7> flag above was added to support sound in testing
move.w (sp)+,sr ; restore interrupt level
movem.l (sp)+,d0-d5/a0-a4 ; restore registers
RTS6 ; return to caller
;;;; sound test utility routines and data
;
; init the sound registers to their reset condition
; assumes a1 = sound device base <7>
;
snd_reg_init ;
move.w d2,d3 ; get boxflag <7>
lsr.w #8,d3 ; <7>
cmpi.b #BoxMacIIsi,d3 ; is it a IIsi (Erickson)? <7><29>
bne.s @ASC ; no, just the ASC regs <7>
move.b #1,ascPlayRecA(a1) ; set record mode, RFD disabled <18><7>
tst.b ascFifoInt(a1) ; clear pending interrupt flags <17><7>
move.b #0,ascPlayRecA(a1) ; set play mode, RFD disabled <18><7>
@ASC move.b #1,ascMode(a1) ; set mode to FIFO <17><7>
move.b #0,ascChipControl(a1) ; set PWM, mono, clear any overrun <17><7>
move.b #$80,ascFifoControl(a1) ; reset the FIFO ptrs <17><7>
move.b #0,ascFifoControl(a1) ; <17><7>
tst.b ascFifoInt(a1) ; clear pending interrupt flags <17><7>
move.b #0,ascWaveOneShot(a1) ; clear one shot modes/flags <17><7>
move.b #0,ascVolControl(a1) ; volume = 0 <17><7>
move.b #0,ascClockRate(a1) ; clk mode = 22.257Khz (Mac) <17><7>
move.b #0,ascTestReg(a1) ; clear any test bits <17><7>
rts ;
;
; register test data, terminates when reg = 0
; for each register number occurance a corresponding datum should be
; able to be written to and read from the register number given
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; new sound chip and sound input register table
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sndrnio ; <19><7>
dc.w ascPlayRecA, 8, $83 ; <19><18><7>
sndrnnew ;
dc.w ascMode, 4, $FF ; <19><18>
dc.w ascChipControl, 13, $7F ; <19><18>
dc.w ascFifoControl, 3, $FF ; <19><18>
dc.w ascFifoInt, 6, $FF ; <19><18>
dc.w ascWaveOneShot, 12, $FF ; <19><18>
dc.w ascClockRate, 4, $FF ; <19><18>
dc.w $FFFF, $FFFF, $FFFF ; <19><18>
; then the corresponding register data...
sndrdio ; <7>
dc.b 0,1,2,3,$81,$82,$83,0 ; register a <7>
sndrdnew ; <7>
dc.b 0,1,2,0 ; 1 <7>
dc.b 0,1,2,4,8,$10,$1e,$1d,$1b,$17,$f,$1f,0 ; 2
dc.b 0,$80,0 ; 3
dc.b 0,1,2,4,8,0 ; 4
dc.b 0,$80,1,2,4,8,7,$b,$d,$e,$f,0 ; 5
dc.b 0,2,3,0 ; 7
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <18>
; Register table for Batman implementation <18>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <18>
sndrnBatman
dc.w ascMode, 3, $03 ;mode register <19><18>
dc.w ascVolControl, 8, $E0 ;volume register (bits 5-7) <19><18>
dc.w ascPlayRecA, 3, $01 ;sound in ctl reg <19><18>
dc.w bmFifoControlA, 9, $FF ;ch A FIFO ctl <19><18>
dc.w bmFifoControlB, 9, $FF ;ch B FIFO ctl <19><18>
dc.w $FFFF, $FFFF, $FFFF ; <19><18>
sndrdBatman
dc.b 0,1,0 ;mode register <19><18>
dc.b 0<<5,1<<5,2<<5,3<<5,4<<5,5<<5,6<<5,7<<5 ;Vol is 0 to 8 in bits 5-7 <19><18>
dc.b 0,1,0 ;play/rec bit-leave in play <19><18>
dc.b 0,1,2,3,$80,$81,$82,$83,0 ;ch A FIFO ctl data <19><18>
dc.b 0,1,2,3,$80,$81,$82,$83,0 ;ch B FIFO ctl data <19><18>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <H15><SM6>
; Register table for Sonora-style Batman implementation <H15><SM6>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <H15><SM6>
sndrnBatRatsSonora ; <H15><SM6>
dc.w ascMode, 1, $01 ;mode register (always 1) <H15><SM6>
dc.w ascVolControl, 8, $E0 ;volume register (bits 5-7) <H15><SM6>
dc.w ascPlayRecA, 3, $01 ;sound in ctl reg <H15><SM6>
dc.w $FFFF, $FFFF, $FFFF ; <H15>
sndrdBatRatsSonora ; <H15><SM6>
dc.b 1 ;mode register <H15><SM6>
dc.b 0<<5,1<<5,2<<5,3<<5,4<<5,5<<5,6<<5,7<<5 ;Vol is 0 to 8 in bits 5-7 <H15><SM6>
dc.b 0,1,0 ;play/rec bit-leave in play <H15><SM6>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <8>
; Register table for VISA implementation <8>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <8>
sndrnVISA ; <19><18><8>
dc.w ascMode, 1, $FF ;Mode reg (always 1) <19><18><8>
dc.w ascChipControl, 1, $7F ;Chip control (always 1) <19><18>
dc.w ascVolControl, 8, $FF ;volume register (bits 5-7) <19><18>
dc.w ascPlayRecA, 5, $FF ;sound in ctl reg <19><18>
dc.w $FFFF, $FFFF, $FFFF ; <19><18>
; then the corresponding register data... <19><18><8>
sndrdVISA ; <19><18><8>
dc.b 1 ;mode register <19><18>
dc.b 1 ;Chip control <19><18>
dc.b 0<<5,1<<5,2<<5,3<<5,4<<5,5<<5,6<<5,7<<5 ;Vol is 0 to 8 in bits 5-7 <19><18>
dc.b 0,1,2,3,0 ;play/rec bit-leave in play <19><18>
align
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; (old sound chip register table)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sndrnold ; <19><18>
dc.w ascMode, 4, $FF ; <19><18>
dc.w ascChipControl, 5, $7F ; <19><18>
dc.w ascFifoControl, 9, $FF ; <19><18>
dc.w ascFifoInt, 6, $FF ; <19><18>
dc.w ascWaveOneShot, 12, $FF ; <19><18>
dc.w ascClockRate, 4, $FF ; <19><18>
dc.w $FFFF, $FFFF, $FFFF ; <19><18>
; then the corresponding register data... ;
sndrdold ;
dc.b 0,1,2,0 ; register 1
dc.b 0,1,2,3,0 ; 2
dc.b 0,1,2,$80,3,$81,$82,$83,0 ; 3
dc.b 0,1,2,4,8,0 ; 4
dc.b 0,$80,1,2,4,8,7,$b,$d,$e,$f,0 ; 5
dc.b 0,2,3,0 ; 7
noASC moveq #-1,d6 ;load fail/no-log code
RTS6 ;return to caller
;-------------------------------------------------------------------------------
;
; #8A: PRAM TEST
; This module tests the extended Pram non-destructively. It writes test data
; to all locations and verifies. Test data is rotated to generate different
; data patterns.
;
; Inputs: a0 - points to table of hardware base addresses
; a1 - pointer to product information table
; d0 - bits indicating which base address are valid
; d2.lw - boxflag/decoder type
; d2.hw - private feature flags
;
; Outputs: d6 - $0, no error
; $00xxyyzz, xx = failed address
; yy = expected value
; zz = actual value
; Destroys: ?
;
; Called by BSR6
;-------------------------------------------------------------------------------
; From here to the next <9> label below is the new PRAM test with improved
;tolerance for power failures during ROM Burn-in
PramTest ;
move.l a6,-(sp) ;save return address
movea.l DecoderInfo.VIA1Addr(a0),a2 ;point to VIA1 base <21>
;
; First, save all of PRAM
;
move.l #$FF,d3 ;Start at address zero.
movea.l sp,a3 ;save the current stack pointer
lea -256(sp),sp ;reserve room on the stack
@saveloop
move.l a3,-(sp) ;save the save address
move.l d3,d1 ;address to read byte from
BSR6 RdXByte ;
move.l (sp)+,a3 ;restore the save address
move.b d1,-(a3) ;save the byte
dbra d3,@saveloop
;
; Next, test the lower half of PRAM. In case we're in RBI,
; invalidate the locations that would contain the signature bytes.
; These will be restored later.
;
BSR6 ClkWpOff ;Turn off the clock write protect bit
move.l #SigLocs,d1 ;then invalidate the signature byte
swap d1 ;get the lower signature address
moveq.l #0,d2 ;Write a zero to one of the sig byte locations
BSR6 WRXBYTE
;
; Now we're free to trash the lower half of PRAM.
;
move.w #0,-(sp) ;Starting address of test
move.w #$7F,-(sp) ;Ending address of test
bsr PRAMParamTest ;Call the parameterized PRAM test.
lea 4(sp),sp ;Clean up the stack
tst.l d6 ;Was there an error? <11>
bne.s @return ;Return now if so <11>
bsr RestoreallPRAM ;Restore all of PRAM now
move.l #SigLocs,d1 ;then invalidate the upper signature byte
moveq.l #0,d2 ;Write a zero to one of the sig byte locations
BSR6 WRXBYTE
move.w #$80,-(sp) ;now we're free to test the upper half of PRAM
move.w #$FF,-(sp) ;Ending address to test
bsr PRAMParamTest ;test the upper half of PRAM
lea 4(sp),sp ;clean up the stack
@return ; <11>
bsr RestoreallPRAM ;restore all of PRAM again (for the last time)
lea 256(sp),sp ;clean up the stack
rts
;-------------------------------------------------------------------------------
;
; This routine restores PRAM from the saved area. It is assumed that the save
; area begins immediately above the return address on the stack. PRAM is
; restored from low addresses to high addresses.
;
;-------------------------------------------------------------------------------
RestoreallPRAM
lea 4(sp),a3 ;get the save area
moveq.l #0,d3 ;start at 0
@restoreloop
move.b (a3)+,d2 ;get the next byte
move.l d3,d1 ;address to restore next
move.l a3,-(sp) ;save the save area pointer
BSR6 WRXBYTE ;
move.l (sp)+,a3 ;restore the save area pointer
addq.w #1,d3 ;
cmp.w #256,d3 ;all bytes saved?
bne.s @restoreloop ;next byte
rts
;-------------------------------------------------------------------------------
;
; This is the parameterized PRAM test. The parameters are contained on the stack
; when this routine is called. Upon entry the stack must look like this:
; (sp) -> return address (called with a normal bsr instruction)
; 4(sp) -> ending address of PRAM to test
; 6(sp) -> starting address of PRAM to test
;
; Note that this is a destructive test. The caller must already have saved the
; PRAM contents before calling this function.
;
;-------------------------------------------------------------------------------
PRAMParamTest
moveq.l #0,d6 ;Initialize the results to passed
move.w 6(sp),d3 ;Get the starting address to test
@fillLoop
move.w d3,d1 ;Get the next address
move.w #$A5,d2 ;Write a pattern to it
BSR6 WRXBYTE
move.w d3,d1 ;Restore the PRAM address under test
BSR6 RDXBYTE ;and read back the result
cmpi.b #$A5,d1 ;Is this what we wrote?
beq.s @OK ;continue if OK
move.b d3,d6 ;PRAM failure! Report the failed address
rol.l #8,d6
move.b #$A5,d6 ;report the expected pattern
rol.l #8,d6
move.b d1,d6 ;and report the actual pattern
bra.s @done ;then exit immediately
@OK addq.w #1,d3 ;Increment the test address
cmp.w 4(sp),d3 ;are we done yet?
ble.s @fillLoop ;continue if we're not done yet
@done rts
; From here to the previous <9> label above is the new PRAM test with improved
;tolerance for power failures during ROM Burn-in
TestRBV ;
;-------------------------------------------------------------------------------
;
; #8B: RBV Chip test
; this is a register test of the RBV chip
; it checks for proper response of the read/write registers
; in response to canned patterns
;
; Inputs: a0 - points to table of hardware base addresses
; a1 - Pointer to Product Info record <12>
; d0 - bits indicating which base address are valid
; d2.lw - boxflag/decoder type
; d2.hw - private feature flags
;
; Outputs: d6.l = 0 if test passes
; d6.l = wwxxyyzz, where
; ww -> undefined
; xx -> register under test at address RBVBase + $xx
; yy -> expected value
; zz -> actual value
; Destroys: ?
;
; Called by BSR6
;-------------------------------------------------------------------------------
move #0,CCR ; clear extend bit
clr.l d6 ; clear error register
clr.l d5 ; clear 'actual value' register
clr.l d4 ; clear 'expected value' register
btst.l #DecoderInfo.RBVExists,d0 ; do we have an RBV? <21>
beq noRBV ; no, exit
movea.l DecoderInfo.RBVAddr(a0),a0 ; Get RBV base <21>
lea rbvrn,a2 ; get reg ptr for rbv test register
lea rbvrd,a3 ; get reg ptr for rbv test data
WITH ProductInfo ; <12>
move.l ExtValid(a1),d1 ;Get the external valid flags <12>
btst.l #V8ChipBit,d1 ;Do we have a V8 RBV? <12><2>
beq.s @checkSonora ;Continue if not <12>
lea rbvrdVISA,a3 ;Else use the VISA RBV register table <12>
bra.s @3 ; start the test <H15><SM6>
@checkSonora
btst.l #SonoraExistsBit,d1 ; check for Sonora variant <H15><SM6>
beq.s @3 ; continue if not <H15><SM6>
lea rbvrdSonora,a3 ; else use the Sonora RBV register table<H15><SM6>
ENDWITH ; <12>
@3 clr.l d1 ;make sure d1 is clear <12>
move.b (a2)+,d1 ; load up register under test
bmi @15 ; until terminator encountered
move.b (a3)+,d2 ; load bit mask
moveq #-1,d4 ; load initial test data
move.b (a0,d1.w),-(sp) ; store original data <12>
@4 move.b d4,d3 ; save a copy
tst.b d1 ; is this via2 data reg?
bne.s @4a ; nope
ori.b #$0D,d4 ; leave power and external cache alone
@4a and.b d2,d4 ; mask out unwanted bits <12>
move.b d4,(a0,d1.w) ; write to RBV register <12>
move.b (a0,d1.w),d5 ; read back contents <12>
and.b d2,d5 ; mask out unwanted bits
cmp.b d4,d5 ; compare actual vs. expected
bne @9 ; error--get out of town!
move.b d3,d4 ; work with original copy
roxr.b #1,d4 ; walk a zero on through
cmp.b #-1,d4 ; are we done walking zeroes?
bne.s @4 ; nope, keep going
roxr.b #1,d4 ; rotate a one into extend field
clr.b d4 ; clear rest of data register
@6 move.b d4,d3 ; save a copy
tst.b d1 ; is this via2 data reg?
bne.s @6a ; nope
ori.b #$d,d4 ; leave power and external cache alone
@6a and.b d2,d4 ; mask out unwanted bits <12>
move.b d4,(a0,d1.w) ; write to RBV register <12>
move.b (a0,d1.w),d5 ; read back contents <12>
and.b d2,d5 ; mask out unwanted bits
cmp.b d4,d5 ; compare actual vs. expected
bne @9 ; error--get out of town!
move.b d3,d4 ; work with original copy
roxr.b #1,d4 ; walk a one on through
bne.s @6 ; keep going till back to zero
roxr.b #1,d4 ; rotate a zero into extend field
move.b (sp)+,(a0,d1.w) ; restore original data <12>
bra @3 ; check next rbv register
@9 move.b (sp)+,(a0,d1.w) ; error exit <12>
bra @29 ; go home, eh!
;next check interrupt enable/flag register--play weird games with set/clear bit
@15 move.b (a2)+,d1 ; load up register under test
bmi @10 ; until terminator encountered
move.b (a0,d1.w),-(sp) ; store original data <12>
move.b (a3)+,d2 ; load bit mask
move.b d2,(a0,d1.w) ; clear out data <12>
moveq #$1,d4 ; load initial test data
@17 add #$80,d4 ; add set/clear vector
move.b d4,(a0,d1.w) ; write to RBV register <12>
move.b (a0,d1.w),d5 ; read back contents <12>
and.b d2,d5 ; mask out unwanted bits
bclr #7,d4 ; clear out set bit
move.b d4,d3 ; work with copy
and.b d2,d3 ; mask out unwanted bits
cmp.b d3,d5 ; compare actual vs. expected
beq @17a ; keep on truckin'
move.b d3,d4 ; expected value
bra @28 ; error exit
@17a move.b d4,(a0,d1.w) ; write to RBV register <12>
move.b (a0,d1.w),d5 ; read back contents <12>
and.b d2,d5 ; mask out unwanted bits
tst.b d5 ; check results
beq @18 ; should be zero
clr.b d4 ; it wasn't--error
bra @28 ; error exit
@18 rol.b #1,d4 ; walk a one on through
cmp.b #$80,d4 ; are we done walking ones?
bne.s @17 ; nope, keep going
moveq #$1,d4 ; load initial test data
@19 move.b #-1,(a0,d1.w) ; write to RBV register <12>
move.b (a0,d1.w),d5 ; read back contents <12>
bclr #7,d5 ; clear out set bit
cmp.b d2,d5 ; compare actual vs. expected
beq @21 ; read mask, so all ok
move.b d2,d4 ; set up expected value
bra @28 ; error exit
@21 move.b d4,(a0,d1.w) ; write to RBV register <12>
move.b (a0,d1.w),d5 ; read back contents <12>
eori.b #-1,d5 ; complement contents
and.b d2,d5 ; mask out unwanted bits
move.b d4,d3 ; work with copy
and.b d2,d3 ; mask out unwanted bits
cmp.b d3,d5 ; compare actual vs. expected
beq @20 ; keep on truckin'
move.b d3,d4 ; expected value
bra @28 ; error exit
@20 rol.b #1,d4 ; walk a one on through
cmp.b #$80,d4 ; are we done walking ones?
bne.s @19 ; nope, keep going
move.b d2,(a0,d1.w) ; reset register contents <12>
move.b (sp)+,d0 ; restore original data
ori.b #$c0,d0 ; make sure data is set
move.b d0,(a0,d1.w) ; restore original data <12>
bra @15 ; next register
; error exit
@28 move.b d2,(a0,d1.w) ; reset register contents <12>
move.b (sp)+,d0 ; restore original data
ori.b #$c0,d0 ; make sure data is set
move.b d0,(a0,d1.w) ; restore original data <12>
@29 move.b d1,d6 ; move register number to fail code
rol.l #8,d6 ; go to next byte
move.b d4,d6 ; move expected data to fail code
rol.l #8,d6 ; go to lsb
move.b d5,d6 ; move actual data to fail code
@10 RTS6 ;return to caller
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; rbv chip register table
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
rbvrn ;
dc.b $00,$10,$11 ;run bit patterns
dc.b -1 ;
dc.b $12,$13 ;bit 7 is set/clear
dc.b -1 ;
align
; then the corresponding register data...
rbvrd ;
dc.b $8f,$c3,$ff ; mask for bit patterns
dc.b $7f,$1f ; mask for set/clear patterns
align
rbvrdVISA ;VISA RBV variant <12>
dc.b $08,$02,$00 ; mask for bit patterns <12>
dc.b $78,$7F ; mask for set/clear patterns <12><28>
align
rbvrdSonora ; Sonora RBV variant <H15><SM6>
dc.b $0F,$00,$00 ; mask for bit patterns <H15><SM6>
dc.b $78,$7F ; mask for set/clear patterns <H15><SM6>
noRBV moveq #-1,d6 ;load fail/no-log code
RTS6 ;return to caller
TestSWIM
;______________________________________________________________________________
;
; #8C: TestSWIM
;
; Routine: Chk4SWIM
;
; Inputs: a0 - points to table of hardware base addresses
; d0 - bits indicating which base address are valid
; d2.lw - boxflag/decoder type
; d2.hw - private feature flags
;
; Outputs: A0,D0 are trashed
; D6 = status
; D7 = XXXX008C ErrSWIMTest
;
; Function: Checks for the presence of a SWIM. This code was taken from Sony Driver routine
; Check4SWIM. Using the magic sequence the SWIM chip is forced from IWM mode
; to ISM mode. If this is successful, then we must be a SWIM chip. In the ISM mode,
; we can read back the phases that we write. We try to write and read back three
; different phase values.
;
; Assumptions: All interrupts disabled.
; If not a SWIM chip, then set up IWM chip into [Q7-Q6-Motor]=[001]
;______________________________________________________________________________
Chk4SWIM
btst.l #DecoderInfo.IWMExists,d0 ;do we have an IWM/SWIM (not IOP based)? <21>
bne.s @chipExists
moveq #-1,d6 ;load fail/no-log code
RTS6 ;return to caller
@chipExists
MOVE SR,-(SP) ;Save SR
ORI #HiIntMask,SR ;and disable interrupts
movea.l DecoderInfo.VIA1Addr(a0),a2 ; <21>
movea.l DecoderInfo.IWMAddr(a0),a0 ;load IWM/SWIM base address <21>
ADDA.w #VBufD,A2
TST.B IntDrive(A0) ;Be sure the internal drive is selected
TST.B Q7L(A0) ;Select the mode register
TST.B MtrOff(A0)
TST.B Q6H(A0) ;get into status mode [Q7-Q6-Motor]=[010]
;
MOVEQ #$40+iwminitmode,D0 ;set bit 6 to ISM mode and use the magic sequence
MOVE.B D0,Q7H(A0) ;Try to put the chip into ISM mode
MOVE.B #iwminitmode,Q7H(A0) ;The "magic sequence" is to set bit 6
MOVE.B D0,Q7H(A0) ; to "1", "0", "1", "1" over four
MOVE.B D0,Q7H(A0) ; consecutive accesses
MOVEQ #$F5-256,D0 ;If we can write to the phase register
MOVE.B D0,wPhase(A0) ;and read back the same value, this
nop ;delay
CMP.B rPhase(A0),D0 ;must be an SWIM
BNE NoSWIMChip ;-> mismatch: IWM
MOVEQ #$F6-256,D0 ;try again
MOVE.B D0,wPhase(A0)
nop ;delay
CMP.B rPhase(A0),D0
BNE NoSWIMChip ;-> mismatch: IWM
MOVEQ #$F7-256,D0 ;try again
MOVE.B D0,wPhase(A0)
nop ;delay
CMP.B rPhase(A0),D0
BNE NoSWIMChip ;-> mismatch: IWM
move.b #$BF,wZeroes(a0) ; disable the drives so we don't kick <H15><SM6>
; out a floppy on a Swim2 machine <H15><SM6>
bra ISMModeTest ;continue going
NoSWIMChip
move.l #-2,d6 ;swim chip not installed
bra NoSWIM ;get out of town, eh!!!
;
;continue to check out ISM mode of SWIM chip
;
;______________________________________________________________________________
;
; Routine: ISMModeTest
;
; Inputs: a0 - points to table of hardware base addresses
; d0 - bits indicating which base address are valid
; d2.lw - boxflag/decoder type
; d2.hw - private feature flags
;
; Outputs: A0,D0 are trashed
;
;
; D6 = 00000000 no error
; = FFFFFFFE swim chip not installed
; = 01YY00XX Phase error
; = 02YY00XX Parameter RAM register counter error
; = 03YY00XX Parameter RAM data line error
; = 04YY00XX Parameter RAM error
; = 05YY00XX Setup Register error
; = 06YY00XX Write Zero Error
; = 07YY00XX Mode Register Bit Error
; = 08YY00XX Status Register Error
;
; where YY is the actual byte and XX is the expected byte
;
; D7 = XXXX008B ErrSWIMTest
;
; Function: Checks for the presence of a SWIM. This code was taken from Sony Driver routine
; Check4SWIM. Using the magic sequence the SWIM chip is forced from IWM mode
; to ISM mode. If this is successful, then we must be a SWIM chip. In the ISM mode,
; we can read back the phases that we write. We try to write and read back three
; different phase values.
;
; Assumptions: All interrupts disabled.
; If not a SWIM chip, then set up IWM chip into [Q7-Q6-Motor]=[001]
;______________________________________________________________________________
;
; we must be a SWIM chip in ISM mode
ISMModeTest ;check phase register
clr.l d6 ;clear error register
PhaseRegTest
;
lea phasedata,a1 ;fetch phase test data
move.w #16-1,d1 ;set up loop counter for 16
phaseloop
move.b 0(a1,d1),wPhase(a0) ;write test data
nop ;delay a sec
move.b rPhase(a0),d0 ;then, read back result
cmp.b 0(a1,d1),d0 ;read back test data and compare with expected
bne PhaseErr ;if error
dbra d1,phaseloop ;repeat until all combinations tested
;______________________________________________________________________________
; at this point see if we have a SWIM2, if so, skip the pRAM tests
;
; But wait! Don't skip the PRAM tests, just branch down and test the SWIM2 PRAM: <SM6>
bsr Check4SWIM2 ; SWIM2 present? <3><CMP><SM6>
; beq.w SetupRegTest ; yes, skip pRAM tests <3><CMP><SM6>
beq.w Swim2PramTest ; yes, test Swim2 pRAM <3><CMP><SM6>
ParameterRAMTest ;check parameter RAM
link a4,#-16 ;allocate space for current parameter values
move.b rSetup(a0),d4 ;save current setup register
move.b #$00,wSetup(a0) ;
move.b #$38,wZeroes(a0) ;clear parameter register counter
move.w #16-1,d1 ;set up to test 16 bytes of parameter RAM
savepRAM move.b (a2),(a2) ;allow parameter register counter to reset
move.b rParams(a0),0(sp,d1) ;save parameter RAM value on stack (upper byte valid)
dbra d1,savepRAM ;save all 16 values
;
;______________________________________________________________________________
;check parameter register counter
;
lea registerdata,a1 ;
move.w #5-1,d2 ;
tryagain
move.b #$38,wZeroes(a0) ;clear parameter register counter
move.w #16-1,d1 ;set up to test 16 bytes of parameter RAM
clr.l d0
pRAMLoop1 move.b (a2),(a2) ;allow parameter register counter to reset
move.b 0(a1,d1),wParams(a0) ;write to parameter RAM byte
dbra d1,pRAMLoop1 ;repeat until all 16 bytes written to
dbra d2,tryagain ;try four times to get data into parameter RAM
lea expecteddata,a1
move.b #$38,wZeroes(a0) ;clear parameter register counter
clr.l d0 ;
clr.l d2
move.w #16-1,d1 ;set up to test 16 bytes of parameter RAM
move.b (a2),(a2)
pRAMLoop2 move.b (a2),(a2) ;allow parameter register counter to reset
move.b rParams(a0),d0 ;read back
cmp.b 0(a1,d1),d0 ; and compare parameter RAM bytes
bne pRegCntErr ;=>mismatch =>register counter error
dbne d1,pRAMLoop2 ;
;______________________________________________________________________________
clr.l d0 ;check parameter RAM data bit
move.l #8-1,d2 ;check each data bit in the data register
move.l #1,d3 ;test data
pRAMDataTest
move.b #$38,wZeroes(a0) ;clear parameter register counter
move.w #16-1,d1 ;set up to test 16 bytes of parameter RAM
pRAMLoop3 move.b (a2),(a2) ;allow parameter register counter to reset
move.b d3,wParams(a0) ;write same data into parameter RAM
dbra d1,pRAMLoop3 ;
move.b #$38,wZeroes(a0) ;clear parameter register counter
move.w #16-1,d1 ;set up to test 16 bytes of parameter RAM
pRAMLoop4 move.b (a2),(a2) ;allow parameter register counter to reset
move.b rParams(a0),d0 ;check if count is correct
cmp.b d3,d0 ;
bne pRAMDataErr ;
dbra d1,pRAMLoop4 ;
rol #1,d3 ;rotate next bit
dbra d2,pRAMDataTest ;repeat until all parameter RAM tested
;______________________________________________________________________________
clr.l d0 ;check parameter RAM data bit
move.l #256-1,d2 ;check each RAM location
ISMpRAMTest
move.b #$38,wZeroes(a0) ;clear parameter register counter
move.w #16-1,d1 ;set up to test 16 bytes of parameter RAM
pRAMLoop5 move.b (a2),(a2) ;allow parameter register counter to reset
move.b d2,wParams(a0) ;write same data into parameter RAM
dbra d1,pRAMLoop5 ;repeat for 16 bytes
move.b #$38,wZeroes(a0) ;clear parameter register counter
move.w #16-1,d1 ;set up to test 16 bytes of parameter RAM
pRAMLoop6 move.b (a2),(a2) ;allow parameter register counter to reset
move.b rParams(a0),d0 ;check if count is correct
cmp.b d2,d0 ;
bne ISMpRAMErr ;
dbra d1,pRAMLoop6 ;
dbra d2,ISMpRAMTest ;repeat until all parameter RAM tested
lea SetupRegTest,a5 ;everything okay
jmp RestorePRAM
;______________________________________________________________________________
Swim2PramTest ; <SM6>begin
; Here is where the Swim2 PRAM test code will reside. We won't get here
; unless there is a Swim2, and after leaving we will drop down to the
; SetupRegTest routine.
; Start by saving off the current Swim2 pram on the stack:
link a4,#-4 ; allocate space for Swim2 parameter values
move.b rSetup(a0),d4 ; save current setup register
move.b #$00,wSetup(a0) ;
move.b #$38,wZeroes(a0) ; clear parameter register counter
move.w #4-1,d1 ; set up to test 4 bytes of parameter RAM
; with special considerations (some bits
; aren't read/write)
savepSwim2RAM
move.b (a2),(a2) ; allow parameter register counter to reset
move.b rParams(a0),0(sp,d1) ; save parameter RAM value on stack (upper byte valid)
dbra d1,savepSwim2RAM ; save all 4 values
; Now stuff four bytes of test data into the Swim2 pram:
lea registerdata,a1 ; it's OK to use the same 4 bytes as the regular
; Swim chip, but for comparing I will need to
; do some masking because only two nibbles are
; valid in Swim2's PRAM
lea Swim2Masks,a3 ; before stuffing the test data, mask it according
; to the "valid" bits of Swim2 pram
move.w #5-1,d2 ; prepare to try writing a few times to make it stick
Swim2tryagain
move.b #$38,wZeroes(a0) ; clear parameter register counter
move.w #4-1,d1 ; set up to test the 4 bytes of Swim2 PRAM
clr.l d0
Swim2PRAMLoop1
move.b (a2),(a2) ; allow parameter register counter to reset
move.b (a1,d1),d0 ; get a test byte
and.b (a3,d1),d0 ; mask it
move.b d0,wParams(a0) ; write the "adjusted" (masked) test data to Pram
dbra d1,Swim2PRAMLoop1 ; repeat until all 4 bytes written to
dbra d2,Swim2tryagain ; try four times to get data into parameter RAM
; OK, now read back the data and compare it to the expected data. The tricky thing
; here is that of the four bytes of Swim2 pram, only 2 nibbles are valid. Therefore,
; some masking will have to be done before validating the write/read values:
lea expecteddata,a1 ; it's OK to use the Swim expected data, but it will
; be necessary to mask the values for certain bytes
; because not all bits are read/write
move.b #$38,wZeroes(a0) ; clear parameter register counter
clr.l d0 ;
clr.l d2
move.w #4-1,d1 ; set up to test 4 bytes of parameter RAM
move.b (a2),(a2) ; a little delay for the hardware
Swim2PRAMLoop2
move.b (a2),(a2) ; allow parameter register counter to reset
move.b rParams(a0),d0 ; read back
and.b (a3,d1),d0 ; mask it for legitimacy
move.b (a1,d1),d3 ; get the expected data <H15>
and.b (a3,d1),d3 ; mask it because of the funky way Swim2 PRAM works <H15>
cmp.b d3,d0 ; and compare parameter RAM bytes <H15>
bne Swim2pRegCntErr ; =>mismatch =>register counter error
dbne d1,Swim2PRAMLoop2 ; test all 4 bytes
; Well, nothing has failed so far. So, test each bit of the 4 bytes of Swim2
; PRAM, but take into account that not all bits are read/write. This is copied
; from the regular Swim PRAM test. It just starts with a value of 255 (all bits
; set), writes it to all PRAM bytes, and keeps decrementing that value and writing
; it to all PRAM bytes. This is how they make sure all bits are tested. Of course,
; make sure to account for bits that aren't read/write:
clr.l d0 ; check parameter RAM data bit
move.w #16-1,d2 ; cycle through 16 data bytes
lea swim2BitData,a1 ; use the 16 bytes of test data <H15>
Swim2PRAMBitTest
move.b #$38,wZeroes(a0) ; clear parameter register counter
move.w #4-1,d1 ; set up to test 16 bytes of parameter RAM
Swim2PRAMLoop3
move.b (a2),(a2) ; allow parameter register counter to reset
move.b (a1,d2.w),wParams(a0) ; write test data into parameter RAM <H15>
dbra d1,Swim2PRAMLoop3 ; repeat for 4 bytes
move.b #$38,wZeroes(a0) ; clear parameter register counter
move.w #4-1,d1 ; set up to test 4 bytes of parameter RAM
Swim2PRAMLoop6
move.b (a2),(a2) ; allow parameter register counter to reset
move.b rParams(a0),d0 ; read back data from PRAM <H15>
and.b (a3,d1.w),d0 ; mask the value for safety's sake <H15>
move.b (a1,d2.w),d3 ; get the original data <H15>
and.b (a3,d1.w),d3 ; mask it <H15>
cmp.b d3,d0 ; see if they match <H15>
bne Swim2PRAMBitTestErr ; log an error if there is one
dbra d1,Swim2PRAMLoop6
dbra d2,Swim2PRAMBitTest ; repeat until all parameter RAM tested
lea SetupRegTest,a5 ; everything okay, so restore PRAM and continue
; with the rest of the "regular Swim" tests
jmp RestoreSwim2PRAM
;______________________________________________________________________________ <SM6>end
;______________________________________________________________________________
SetupRegTest ;check setup register
;
move.b rSetup(a0),d3 ;save current Setup Register values
;
move.w #8-1,d1 ;set loop counter to 8
move.l #1,d2 ;
SetupLoop ;
move.b d2,wSetup(a0) ;write test bit into setup register
move.b rSetup(a0),d0 ;read setup register and check data
cmp.b d2,d0
bne SetupErr ;
rol #1,d2 ;shift to next bit
dbra d1,SetupLoop ;repeat until all bits shifted and tested
move.b d3,wSetup(a0) ;restore original setup values
;
;______________________________________________________________________________
ModeRegTest
;check mode and status register
move.b rStatus(a0),d3 ;save current Status Register values
move.w #8-1,d1 ;set loop counter to 8/bit number
move.b #$BF,wZeroes(a0) ;set all register bits to zero except ISM mode
move.b rStatus(a0),d0 ;
and.b #$BF,d0 ;leave bit 6 unchanged- ISM mode
bne WrZeroErr ;verify bits set to zero
NextBitLoop
clr.l d2 ;
bset d1,d2 ;set appropriate bit in d2
move.b d2,wOnes(a0) ;set bit high into mode register
move.b rStatus(a0),d0 ;read data back
btst d1,d0 ;test bit for high
beq ModeBitErr ;if bit is zero => error
cmp.b #6,d1 ;skip if ISM mode bit=> must leave in ISM mode
beq.s SkipBit6 ;
move.b d2,wZeroes(a0) ;otherwise, set bit low
move.b rStatus(a0),d0 ;read back data
and.b #$BF,d0 ;leave bit 6 unchanged
bne WrZeroErr ;verify all 8 bits set to zero
SkipBit6
dbra d1,NextBitLoop ;
jmp RestoreModeReg ;
;______________________________________________________________________________
RestorePRAM ;restore the parameter RAM values from the stack
;
move.b #$38,wZeroes(a0) ;clear parameter register counter
move.w #16-1,d1 ;set up to test 16 bytes of parameter RAM
restoreParamRAM move.b (a2),(a2) ;allow parameter register counter to reset
move.b 0(sp,d1),wParams(a0) ;restore parameter RAM value from stack (upper byte valid)
dbra d1,restoreParamRAM ;restore all16 values
move.b d4,wSetup(a0) ;
unlk a4 ;
jmp (a5) ;
;______________________________________________________________________________
RestoreSwim2PRAM ; restore the Swim2 PRAM values from the stack <SM6>begin
;
move.b #$38,wZeroes(a0) ; clear parameter register counter
move.w #4-1,d1 ; set up to test 16 bytes of parameter RAM
restoreSwim2ParamRAM
move.b (a2),(a2) ; allow parameter register counter to reset
move.b 0(sp,d1),wParams(a0) ; restore parameter RAM value from stack (upper byte valid)
dbra d1,restoreSwim2ParamRAM ; restore all 4 values
move.b d4,wSetup(a0) ;
unlk a4 ;
jmp (a5) ; <SM6>end
;______________________________________________________________________________
PhaseErr
move.b rPhase(a0),d6
or.w #$0100,d6
swap d6
or.b (a1,d1),d6
bra testdone
;______________________________________________________________________________
pRegCntErr
move.b 0(a1,d1),d2 ;
move.b d0,d6 ;load error value into d6
or.w #$0200,d6 ;set flag into d6
swap d6
or.w d2,d6 ;load expected value into d6
lea testdone,a5
jmp RestorePRAM
;______________________________________________________________________________
Swim2PRegCntErr ; <SM6>
move.b 0(a1,d1),d2 ; <SM6>
move.b d0,d6 ;load error value into d6 <SM6>
or.w #$0900,d6 ;set flag into d6 <H15> <SM6>
swap d6 ; <SM6>
or.w d2,d6 ;load expected value into d6 <SM6>
lea Swim2testdone,a5 ; <SM6>
jmp RestoreSwim2PRAM ; <SM6>
;______________________________________________________________________________
pRAMDataErr
move.b d0,d6 ;load error value into d6
or.w #$0300,d6 ;set flag
swap d6 ;
or.w d3,d6 ;load expected data into d6
lea testdone,a5
jmp RestorePRAM
;______________________________________________________________________________
ISMpRAMErr
move.b d0,d6 ;load error value into d6
or.w #$0400,d6 ;set flag
swap d6 ;
or.w d2,d6 ;load expected data into d6
lea testdone,a5
jmp RestorePRAM
;______________________________________________________________________________
Swim2PRAMBitTestErr ; <SM6>
move.b d0,d6 ;load error value into d6 <SM6>
or.w #$0A00,d6 ;set flag <H15> <SM6>
swap d6 ; <SM6>
or.w d2,d6 ;load expected data into d6 <SM6>
lea Swim2testdone,a5 ; <SM6>
jmp RestoreSwim2PRAM ; <SM6>
;______________________________________________________________________________
SetupErr
move.b d0,d6 ;load error value into lsb of d6
or.w #$0500,d6 ;set flag for setup register error
swap d6
or.w d2,d6 ;load expected data into d6
move.b d3,wSetup(a0) ;restore original setup values
jmp testdone
;______________________________________________________________________________
WrZeroErr
move.b d0,d6 ;load error value into lsb of d6
or.w #$0600,d6 ;set flag for write zero error
swap d6
or.w #$0000,d6 ;load expected data into d6
jmp RestoreModeReg ;restore original mode status
;______________________________________________________________________________
ModeBitErr
move.b d0,d6 ;load error value into lsb of d6
or.w #$0700,d6 ;set flag for mode register bit error
swap d6
or.w d2,d6 ;load expected data into d6
jmp RestoreModeReg ;restore original mode status
;______________________________________________________________________________
StatusRegErr
move.b rStatus(a0),d6 ;load error value into lsb of d6
or.w #$0800,d6 ;set flag for status register error
swap d6
or.w d3,d6 ;load expected data into d6
jmp testdone
;______________________________________________________________________________
RestoreModeReg
move.w #8-1,d1 ;set loop counter to 8/bit number
ModeBitLoop
clr.l d2 ;
btst d1,d3 ;test to set if bit is zero
beq.s ignoreBit ;if bit is zero, it's already okay
bset d1,d2 ;set appropriate bit high
move.b d2,wOnes(a0) ;write appropriate bit high in mode register
ignoreBit
dbra d1,ModeBitLoop ;
cmp.b rStatus(a0),d3 ;check if all bits are restored
bne.s StatusRegErr ;restored value is bad
;
;Done testing
;
;______________________________________________________________________________
testdone
MOVE.B #$F8,wZeroes(A0);Switch back to IWM register set
NoSWIM TST.B Q7L(A0) ;Back to read state with the drive enabled
TST.B Q6L(A0)
;;; TST.B MtrOn(A0) ;see if we can get away without making noise ***
Swim2testdone ; <SM6>
MOVE (SP)+,SR ;Enable interrupts
RTS6 ;return to caller
;______________________________________________________________________________ <3><CMP>
; Routine: Check4SWIM2 <3><CMP>
; Inputs: A0 -- IWM base <3><CMP>
; Outputs: Z-bit set if SWIM2, cleared otherwise <3><CMP>
; D0 is trashed. <3><CMP>
;______________________________________________________________________________ <3><CMP>
Check4SWIM2 ; <3><CMP>
; if we get to here then we have either a SWIM or SWIM2, if we can get <3><CMP>
; back into IWM mode it is a SWIM, if not it is a SWIM2 <3><CMP>
MOVE.B #$F8,wZeroes(A0) ;Switch back to IWM register set <3><CMP>
MOVEQ #$F5-256,D0 ;If we can write to the phase register <3><CMP>
MOVE.B D0,wPhase(A0) ;and read back the same value, this <3><CMP>
CMP.B rPhase(A0),D0 ;must be an SWIM2 <3><CMP>
BNE.S @1 ;-> mismatch: SWIM <3><CMP>
MOVEQ #$F6-256,D0 ; <3><CMP>
MOVE.B D0,wPhase(A0) ; <3><CMP>
CMP.B rPhase(A0),D0 ; <3><CMP>
BNE.S @1 ;-> mismatch: SWIM <3><CMP>
MOVEQ #$F7-256,D0 ; <3><CMP>
MOVE.B D0,wPhase(A0) ; <3><CMP>
CMP.B rPhase(A0),D0 ; <3><CMP>
RTS ; return with Z-bit set <3><CMP>
@1 ; if we get here we must put the SWIM back into ISM mode <3><CMP>
TST.B IntDrive(A0) ;Be sure the internal drive is selected <3><CMP>
TST.B Q7L(A0) ;Select the mode register <3><CMP>
TST.B MtrOff(A0) ; <3><CMP>
TST.B Q6H(A0) ;get into status mode [Q7-Q6-Motor]=[010] <3><CMP>
; <3><CMP>
MOVEQ #$40+iwminitmode,D0 ;set bit 6 to ISM mode and use the magic sequence <3><CMP>
MOVE.B D0,Q7H(A0) ;Try to put the chip into ISM mode <3><CMP>
MOVE.B #iwminitmode,Q7H(A0) ;The "magic sequence" is to set bit 6 <3><CMP>
MOVE.B D0,Q7H(A0) ; to "1", "0", "1", "1" over four <3><CMP>
MOVE.B D0,Q7H(A0) ; consecutive accesses <3><CMP>
MOVEQ #1,D0 ; return with Z-bit cleared <3><CMP>
RTS ; <3><CMP>
;______________________________________________________________________________
phasedata dc.b $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7,$F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF
registerdata dc.b $FF,$EE,$DD,$CC,$BB,$AA,$99,$88,$77,$66,$55,$44,$33,$22,$11,$00
expecteddata dc.b $FF,$EC,$DD,$CC,$BB,$AA,$99,$88,$77,$66,$55,$44,$33,$22,$11,$00
swim2BitData dc.b $00,$10,$20,$30,$40,$50,$60,$70,$80,$90,$A0,$B0,$C0,$D0,$E0,$F0 ;<H15><SM6>
Swim2Masks ;<SM6>
dc.b $00,$f0,$00,$f0 ;<SM6>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; #8D: Float_Test
; WILL TEST THE GENERAL FUNCTIONALITY OF THE MC68881
; FLOATING-POINT COPROCESSOR AND THE 68020/68881
; COPROCESSOR INTERFACE.
; based on bring up test by steve cox, version 1.1 <v1.7>
;
;
;REGISTER USAGE:
;
;D0 - D4 GENERAL USAGE
;D5 PASS/FAIL FLAG FOR EXCEPTION HANDLER
;D6 SUBTEST #
;D7 EXPECTED EXCEPTION VECTOR #, IF 0 THEN NO EXCEPTIONS EXPECTED
;
;A0 - A3 GENERAL USAGE
;A4 PTR TO TEST SCRATCH AREA
;A5 ORIGINAL VECTOR BASE REGISTER (VBR)
;A6 LOCAL FRAME STORAGE PTR
;A7 STACK
;
;VBR REDIRECTED TO SELF-CONTAINED EXCEPTION HANDLER DURING FPC TESTS
; RESTORED AFTER FINISH. SEE FOLLOWING CODE
;
;ENTRY: A6.L = LOCAL FRAME PTR
; A7.L = ISP
;
;EXIT: IF TEST IS SUCCESSFUL (I.E. ALL SUBTESTS PASS)
; d6 = 0
; D0.UW = COPROCESSOR TYPE, 1 = 68881, 2 = 68882
;
; ELSE
; D6 = FIRST OCCURRING FAILED SUBTEST #
; D0.UW= COPROCESSOR TYPE, 1 = 68881, 2 = 68882
;
;NOTE: COPROCESSOR TYPE MAY BE BOGUS IF COPROCESSOR IS FAIRLY HOSED-UP
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <v1.3>
;;; Floating point test equates <v1.3>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <v1.3>
;LOCAL STORAGE ALLOCATION
N_EXCTAB EQU -1024 ;BASE OF NEW(MY) EXCEPTION TABLE
READ_STR EQU -1300 ;STORAGE FOR DATA READ FROM FPC
FRAME_SZ EQU -1600 ;SIZE OF LOCAL STORAGE
;FLOATING-POINT EXCEPTION VECTOR NUMBERS
TRAP EQU 7 ;TRAPcc and fpTRAPcc & TRAPV
FLINE EQU 11 ;F-LINE TRAP
FPROTV EQU 13 ;COPROC PROTOCOL VIOLATION
FORMAT_ERR EQU 14 ;FORMAT ERROR
FBSUN EQU 48 ;FLOATING POINT BRANCH OR SET UNORDERED
FINEX EQU 49 ;FLOATING POINT INEXACT RESULT
FDIV0 EQU 50 ;"""""""""""""" DIV BY 0
FUNDF EQU 51 ;"""""""""""""" UNDERFLOW
FOPERR EQU 52 ;"""""""""""""" OPERAND ERROR
FOVFL EQU 53 ;"""""""""""""" OVERFLOW
FSNAN EQU 54 ;"""""""""""""" SIGNALLING NOT A NUMBER
;FLOATING-POINT EXCEPTION BYTE BIT (FLAG) DEFINITIONS
EB_BSUN EQU 15 ;BRANCH/SET ON UNORDERED
EB_SNAN EQU 14 ;SIGNALLING NOT A NUMBER
EB_OPERR EQU 13 ;OPERAND ERROR
EB_OVFL EQU 12 ;OVERFLOW
EB_UNFL EQU 11 ;UNDERFLOW
EB_DZ EQU 10 ;DIVIDE BY ZERO
EB_INEX2 EQU 09 ;INEXACT RESULT
EB_INEX1 EQU 08 ;INEXACT RESULT ON DECIMAL INPUT
;FLOATING-POINT ACCRUED EXCEPTION BYTE BIT (FLAGS) DEFS
AEB_IOP EQU 07 ;INVALID OPERATION
AEB_OVFL EQU 06 ;OVERFLOW
AEB_UNFL EQU 05 ;UNDERFLOW
AEB_DZ EQU 04 ;DIVIDE BY ZERO
AE_INX EQU 03 ;INEXACT
;FLOATING-POINT CONDITION CODES (BIT POSITIONS)
FCC_N EQU 27 ;NEGATIVE
FCC_Z EQU 26 ;ZERO
FCC_I EQU 25 ;INFINITY
FCC_NAN EQU 24 ;NOT A NUMBER (NAN)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <v1.3>
Float_Test
MC68881
move.w ProductInfo.HwCfgWord(a1),d3 ;Get the HW configuration word <26>
btst.l #hwCbFPU,d3 ;Is there supposed to be an FPU? <26>
bne.s @FPUInstalled ;Continue with the test is so <26>
moveq.l #-1,d6 ;Else this test does not apply <26>
RTS6 ;return <26>
@FPUInstalled
MOVE.W SR,-(SP) ;SAVE INTERRUPT STATUS
movem.l d2/d7,-(sp) ;save some regs <26>
ori.w #hiIntMask,sr ;turn ints off
LINK A6,#FRAME_SZ ;ALLOCATE SOME STACK SPACE
MOVEQ.L #1,d6 ;INIT SUBTEST# TO 1
CLR.L D5 ;INIT EXCEPT HDLR PASS/FAIL FLAG
CLR.L D7 ;INIT FOR NO EXCEPTIONS EXPECTED
MOVE.W #256-1,D0 ;SET EXCEPTION COUNT
MOVEC.L VBR,A0 ;GET VECTOR BASE REG
MOVE.L A0,A5 ;SAVE ORIGINAL VBR FOR LATER
LEA.L N_EXCTAB(A6),A1 ;PTR TO START OF NEW EXCPT TABLE
MOVE.L A1,A2 ;SAVE BASE OF NEW EXCPT TABLE
FTB1 MOVE.L (A0)+,(A1)+ ;COPY ORIGINAL TABLE TO NEW TABLE
DBRA D0,FTB1 ;DO 256 VECTORS
;POINT FLOATING-POINT COPROCESSOR RELATED VECTORS TO MY HANDLER ROUTINE
;LEAVE OTHERS POINTING TO ORIGINAL OS ROUTINES
;PT FLOATING-POINT RELATED EXCEPTIONS WHICH WILL BE FORCED TO A GENERIC HANDLER
LEA.L FPC_EHND(PC),A0 ;GET PTR TO FLOATING PT EXCEPT HDLR
MOVE.L A0,TRAP*4(A2) ;TRAPCC AND TRAPV
MOVE.L A0,FBSUN*4(A2) ;SET/UNORDERED
MOVE.L A0,FINEX*4(A2) ;INEXACT
MOVE.L A0,FDIV0*4(A2) ;FLOATING PT DIVIDE BY 0
MOVE.L A0,FUNDF*4(A2) ;UNDERFLOW
MOVE.L A0,FOPERR*4(A2) ;OPERAND ERROR
MOVE.L A0,FOVFL*4(A2) ;OVERFLOW
MOVE.L A0,FSNAN*4(A2) ;NOT A NUMBER
; USE DIFFERENT HANDLER FOR POSSIBLE PRE AND MID-INSTRUCTION EXCEPTIONS
; WHICH COULD OCCUR UNEXPECTEDLY DURING FLOATING-POINT COPROC ACCESSES
LEA.L PM_EXCPT(PC),A0 ;GET PTR TO PRE AND MID INST EXCEPT HDLR
MOVE.L A0,FLINE*4(A2) ;FLINE
MOVE.L A0,FPROTV*4(A2) ;COPROC PROTOCOL
MOVE.L A0,FORMAT_ERR*4(A2) ;FORMAT ERROR
MOVEC.L A2,VBR ;PT VBR TO FPC TEST HANDLER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST FOR FPU PRESENCE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 2
LEA.L CP_PRES(PC),A0 ;GET ADDRESS TO GET AROUND POSSIBLE EXCPT
MOVEQ.L #FLINE,D7 ;SET EXPECTED EXCEPTION VECTOR #
FMOVE.L D0,FP0 ;TEST FOR PRESENCE OF FPU
CP_PRES TST.B d5 ;DID F-LINE OR OTHER UNEXPECT EXCPT OCCUR
BNE FAIL ;YES, THEN FPU NOT PRESENT OR OTHER FAIL
CLR.L d5 ;CLEAR EXCEPTION OCCUR FLAG
CLR.L D7 ;CLEAR EXPECTED EXCEPTIONS FLAG
LEA.L READ_STR(A6),A4 ;INIT PTR TO READ DATA TEMP STORAGE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST FMOVE.L TO FLOATING_POINT CONTROL REGISTER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;THIS TEST SHOULD ALSO DISABLE ALL FPC EXCEPTIONS GENERATED BY FPU STATUS
;BITS IN THE FPSR (FLOATING-POINT STATUS REGISTER)
ADDQ.W #1,d6 ;SUBTEST # 3
LEA.L MOVLNGCR(PC),A0 ;PTR TO DATA TO WRITE TO FPC
FMOVE.L (A0),FPCR ;WRITE DATA TO FPC CONTROL REG
FMOVE.L FPCR,(A4) ;READ DATA FROM FPC
BSR VER_DAT ;DOES WRITE = READ
BNE FAIL ;NO RTN FAILED
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;;;;;;;;
; TEST FMOVE TO FPIAR
;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 4
LEA.L MOVLNG1(PC),A0
FMOVE.L (A0),FPIAR ;WRITE TO FP INSTR ADDR. REG
FMOVE.L FPIAR,(A4) ;NOW READ IT
BSR VER_DAT
BNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST FMOVE TO FPIAR AGAIN WITH INVERTED DATA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST #5
LEA.L MOVLNG2(PC),A0
FMOVE.L (A0),FPIAR ;WRITE TO FP INSTR ADDR. REG
FMOVE.L FPIAR,(A4) ;NOW READ IT
BSR VER_DAT
BNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;
; TEST FMOVE.L
;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 6
LEA.L MOVLNG1(PC),A0 ;PTR TO DATA TO WRITE TO FPC
FMOVE.L (A0),FP0 ;WRITE DATA TO FPC
FMOVE.L FP0,(A4) ;READ DATA FROM FPC
BSR VER_DAT ;DOES WRITE = READ
BNE FAIL ;NO RTN FAILED
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
; NOTICE THAT THE FOLLOWING FP REGISTER NUMBERS ARE INCREMENTING SO THAT ALL OF
; THEM ARE USED TO AN EXTENT.
;;;;;;;;;;;;;;;;;;;;
; TEST FMOVE.L AGAIN
;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 7
LEA.L MOVLNG2(PC),A0 ;PTR TO DATA TO WRITE TO FPC
FMOVE.L (A0),FP0 ;WRITE DATA TO FPC
FMOVE.L FP0,(A4) ;READ DATA FROM FPC
BSR VER_DAT ;DOES WRITE = READ
BNE FAIL ;NO RTN FAILED
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;
; TEST FMOVE.W
;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 8
LEA.L MOVWD(PC),A0
FMOVE.W (A0),FP1
FMOVE.W FP1,(A4)
BSR VER_DAT
BNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;
; TEST FMOVE.B
;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 9
LEA.L MOVBT(PC),A0
FMOVE.B (A0),FP2
FMOVE.B FP2,(A4)
BSR VER_DAT
BNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;
; TEST FMOVE.S
;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 10
LEA.L MOVSGL(PC),A0
FMOVE.S (A0),FP3
FMOVE.S FP3,(A4)
BSR VER_DAT
BNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;
; TEST FMOVE.D
;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 11
LEA.L MOVDBL(PC),A0
FMOVE.D (A0),FP4
FMOVE.D FP4,(A4)
BSR VER_DAT
BNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;
; TEST FMOVE.X
;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 12
LEA.L MOVEXT(PC),A0
FMOVE.X (A0),FP5
FMOVE.X FP5,(A4)
BSR VER_DAT
BNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST FMOVE.P FOR STATIC k-FACTOR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 13
LEA.L MOVBCDW(PC),A0 ;PT TO PRECISE VALUE
FMOVE.P (A0),FP6 ;WRITE PRECISE VALUE TO FPC
LEA.L MOVBCDSR(PC),A0 ;NOW POINT TO EXPECTED VALUE FROM FPC
FMOVE.P FP6,(A4){#3} ;READ VALUE FROM FPC, (K-FACTOR = 3)
BSR VER_DAT ;ACTUAL=EXPECTED?
BNE FAIL ;NO, BRANCH
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;TEST FMOVE.P FOR DYNAMIC k-FACTOR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 14
MOVEQ.L #-5,D2 ;SET DYNAMIC K-FACTOR = -5
LEA.L MOVBCDW(PC),A0
FMOVE.P (A0),FP7 ;WRITE PRECISE VALUE TO FPC
LEA.L MOVBCDDR(PC),A0 ;NOW POINT TO EXPECTED VALUE
FMOVE.P FP7,(A4){D2} ;READ VALUE (K-ADJUSTED) FROM FPC
BSR VER_DAT ;ACTUAL=EXPECTED?
BNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST FMOVECR USING PI = 3.1415927 , PACKED BCD k-FACTOR = 7
; CONSTANT RETURNED SHOULD HAVE 7 SIGNIFICANT DIGITS TO RIGHT OF DECIMAL PT.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST #15
FMOVECR.X #0,FP0 ;MOVE PI INTO FP0
LEA.L PI(PC),A0 ;PTR TO EXPECTED VALUE
FMOVE.P FP0,(A4){#-7} ;GET ROUNDED CONSTANT, BCD FORMAT
BSR VER_DAT ;ACTUAL = EXPECTED?
BNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;TEST FMOVEM.X STATIC CASE ONLY
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST #16
LEA.L MOVMEXT(PC),A0 ;PTR TO MOVED IN DATA
MOVE.L A0,A2
LEA.L READ_STR+24(A6),A4 ;PTR TO MOVED OUT DATA
FMOVEM.X (A2)+,FP7/FP2 ;MOVE DATA IN
FMOVEM.X FP7/FP2,-(A4) ;MOVE DATA OUT
BSR VER_DAT
BNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;TEST FSAVE/FRESTORE FOR NULL STATE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 17
LEA.L READ_STR(A6),A2 ;SET UP A STACK AREA
CLR.L -(A2) ;SET FORMAT WORD IN STACK TO NULL
FRESTORE (A2)+ ;NULL SIZE FRESTORE SHOULD RST FPC
;VERIFY THAT SYSTEM REGISTERS ARE CLEAR AFTER FPC SOFTWARE RESET
FMOVEM.L FPCR/FPSR/FPIAR,-(A2) ;SAVE FPC SYSTEM REGS
MOVEQ.L #2,D0 ;SET LOOP CNT
FSRB1 TST.L (A2)+ ;ARE SYSTEM REGISTERS ZERO
DBNE D0,FSRB1 ;CHECK ALL THREE
BNE FAIL ;ALL MUST BE CLEAR OR FAIL
;VERIFY THAT FP0-FP7 CONTAIN NAN'S (NOT A NUMBER) AFTER FPC SOFTWARE RESET
FMOVEM.X FP0-FP7,-(A2) ;GET ALL FP REGISTERS
MOVEQ.L #7,D0 ;LOOP CNT
LEA.L NAN(PC),A1 ;PTR TO NOT A NUMBER
FSRB2 MOVE.L A1,A0 ;PTR FOR COMPARE
CMPM.L (A0)+,(A2)+ ;TEST 1/3 OF A FP REGISTER
BNE.S FSRB3 ;BRANCH IF MISMATCH
CMPM.L (A0)+,(A2)+ ;TEST ANOTHER 1/3
BNE.S FSRB3 ;BRANCH IF MISMATCH
CMPM.L (A0)+,(A2)+ ;TEST LAST 1/3 OF FP REG
FSRB3 DBNE D0,FSRB2 ;GO TEST NEXT FP REG TILL ALL TESTED
BNE FAIL ;FAIL IF ANY MISMATCHES
;VERIFY THAT FSAVE RETURNS NULL FORMAT WORD AFTER FPC SOFTWARE RESET
CLR.L -(A2) ;SET FORMAT WORD FOR NULL IS STACK
FRESTORE (A2) ;NULL FRESTORE RESETS FPC
FSAVE -(A2) ;FSAVE SHOULD RTN A NULL FORMAT WORD
TST.B (A2) ;IS FORMAT WORD NULL
BNE FAIL ;NO, THEN FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; TEST THE BUSY STATE FSAVE/FRESTORE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; A BUSY STATE SAVE AND RESTORE WILL OCCUR BECAUSE THE FREM OPERATION
; (FREM OF A VERY BIG NUMBER BY A VERY SMALL ONE) WILL TAKE A LONG TIME
; (APPROX. 24,000 CYCLES ACCORDING TO MOTOROLA). THE '881 WILL RELEASE
; 68020 AS SOON AS BOTH OPERANDS FOR THE FREM INSTRUCTION HAVE BEEN FETCHED
; AND SUPPLIED TO THE '881.
; THE 68020 WILL COME BACK AND WANT TO DO THE FSAVE BEFORE THE '881 HAS
; COMPLETED THE FREM.
; CONSEQUENTLY, THE '881 WILL MAKE THE DECISION TO DO A BUSY STATE SAVE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;NOTE THAT APPLIED MICRO EMULATOR WILL NOT SINGLE STEP THIS TEST
;I.E. SINGLE-STEPPING WILL CAUSE TEST TO FAIL
;IF USING EMULATOR THEN RUN PAST THE FSAVE AND FRESTORE'S
;AND TEST WILL WORK AS EXPECTED
ADDQ.W #1,d6 ;SUBTEST # 18
LEA.L READ_STR(A6),A2 ;GET SOME STACK SPACE
FMOVE.X BIGNUM(PC),FP0 ;GET BIG NUMBER
FREM.X SMALLNUM(PC),FP0 ;DIVIDE BY SMALL AND CALC REMAINDER
FSAVE -(A2) ;CAUSE BUSY STATE SAVE
CLR.L -(A2) ;SET FORMAT WORD FOR NULL
FRESTORE (A2)+ ;TO DO A SOFTWARE RESET OF FPC
FRESTORE (A2)+ ;NOW DO BUSY STATE RESTORE
LEA.L FREMRSLT(PC),A0 ;PTR TO EXPECTED RESULT
LEA.L READ_STR(A6),A4 ;PTR TO ACTUAL RESULT
FMOVE.X FP0,(A4) ;GET RESULT AFTER RESTORE
BSR VER_DAT ;ACTUAL= EXPECTED
BNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST IDLE STATE FSAVE/FRESTORE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; AN IDLE STATE SAVE AND RESTORE WILL OCCUR BECAUSE THE 68020 WILL NOT
; BE RELEASED BY THE 68881 UNTIL THE FMOVE.X XDENORM(PC),FP1 INSTRUCTION
; IS COMPLETED.
; THE PREVIOUSLY MENTIONED INSTRUCTION WILL CAUSE AN FPC UNDERFLOW EXCEPTION
; HOWEVER THE EXCEPTION WILL NOT BE TAKEN UNTIL IT IS FORCED BY THE
; FNOP INSTRUCTION.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 19
LEA.L READ_STR(A6),A2 ;GET SOME STACK SPACE
MOVEQ.L #EB_UNFL,D0 ;ENABLE FPC UNDERFLOW EXCEPTION
BSR SET_FPCR_BIT ;BY SETTING BIT IN EXCEPT ENABLE
; EXCEPTION WILL BE GENERATED BY THE NEXT INSTRUCTION; HOWEVER IT SHOULD NOT
; BE HANDLED UNTIL THE FNOP INSTRUCTION
FMOVE.X XDENORM(PC),FP1 ;CAUSE UNDERFLOW EXCEPTION
; FSAVE WILL SAVE ANY PENDING EXCEPTIONS AND THEN CLEAR THEM IN THE FPC
FSAVE -(A2) ;IDLE STATE SAVE WILL SAVE PEND EXCEPTIONS
FMOVEM.L FPCR/FPSR,-(A2) ;SAVE EXCEPTION INFO
CLR.L -(A2) ;SET FORMAT TO NULL FOR FPC RESET
FRESTORE (A2)+ ;SOFTWARE RESET FPC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;VERIFY THAT THE INTERNAL STATE INFO WAS CLEARED DURING SOFTWARE RESET BY TRYING
;TO FORCE A PENDING EXCEPTION.
;EXCEPTION SHOULD NOT OCCUR BECAUSE THE RESET REMOVED THE PENDING EXCEPTION CONDITION
FNOP ;FORCE PROCESSING OF PENDING EXCEPT
TST.B d5 ;WAS THERE AN UNEXPECTED EXCEPTION
BNE FAIL ;YES THEN FAILED
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;NOW RESTORE FPC STATE INFO
FMOVEM.L (A2)+,FPCR/FPSR ;RESTORE EXCEPTION INFORMATION
; RESTORE INTERNAL (INTERNAL TO FPC) PENDING EXCEPTION INFO
FRESTORE (A2)+ ;IDLE STATE RESTORE
TST.B d5 ;WAS THERE AN UNEXPECTED EXCEPTION
BNE FAIL ;YES THEN FAILED
MOVEQ.L #FUNDF,D7 ;SET VECT# FOR EXPECTED EXCEPTION
;FORCE PROCESSING OF PENDING FPC EXCEPTION
FNOP ;FORCE PROCESSING OF PENDING EXCEPT
CMPI.B #1,d5 ;EXCEPT PROC OCCUR? VECTOR #'S MATCH
BNE FAIL ;NO THEN FAIL
CLR.L d5 ;CLEAR EXCEPTION PASS/FAIL FLAG
CLR.L D7 ;SET VECT# FOR NO EXPECTED EXCEPTS.
FMOVE.L D7,FPCR ;DISABLE ALL FPC EXCEPTIONS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST FPC STATUS REG SNAN BIT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 20
FMOVE.X SGLNAN(PC),FP0 ;MOVE IN SIGNALLING NAN
FADD.X SGLNAN(PC),FP0 ;CAUSE SNAN BIT TO SET
MOVEQ.L #EB_SNAN,D0 ;TEST FOR SNAN BIT SET
BSR CK_FPSTAT ;DID BIT SET
BEQ FAIL ;NO, FAILED
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST FPC STATUS REG BSUN BIT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 21
MOVEQ.L #EB_BSUN,D0 ;TEST FOR BSUN BIT
FMOVE.X SGLNAN(PC),FP1 ;LOAD SIGNALLING NAN
FBLT.W CKBSUN ;SET BSUN BIT (SHOULD NOT BRANCH)
CKBSUN BSR CK_FPSTAT ;DID BSUN BIT SET
BEQ FAIL ;NO, FAILED
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST FPC STATUS REG DZ BIT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; THIS TEST WILL TEST THE DZ BIT AND A DZ BIT PRE-INSTRUCTION EXCEPTION
; PRE-EXCEPTION WILL BE TAKEN AT FMOVE.L FPSR,D1 IN CK_FPSTAT ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 22
MOVEQ.L #EB_DZ,D0 ;SET BIT FOR DIVIDE BY ZERO
BSR SET_FPCR_BIT ;ENABLE DIVIDE BY ZERO EXCEPTION
FMOVE.X ONE_X(PC),FP2 ;LOAD A ONE
; NEXT INSTRUCT SHOULD CAUSE A PENDING EXCEPTION WHICH WILL BE TAKEN
; DURING THE NEXT FLOATING POINT INSTRUCTION EXECUTED
FDIV.X ZERO_X(PC),FP2 ;DIVIDE BY ZERO
TST.B d5 ;DID UNEXPECTED EXCEPTION OCCUR
BNE FAIL ;YES FAILED
MOVEQ.L #FDIV0,D7 ;SET VECT # FOR EXPECTED EXCEPTION
;EXCEPTION WILL BE TAKEN IN THE FOLLOWING ROUTINE
BSR CK_FPSTAT ;IS DZ BIT SET
BEQ FAIL ;NO FAILED
CMPI.B #1,d5 ;DID EXPECTED EXCEPTIONS OCCUR
BNE FAIL ;NO, FAILED
CLR.L d5 ;CLEAR EXCEPTION OCCURRED FLAG
CLR.L D7 ;CLEAR EXPECTED EXCEPTION VECT #
FMOVE.L D7,FPCR ;DISABLE ALL FPC EXCEPTIONS
;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST STATUS REG OVFL BIT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; THIS TEST WILL TEST THE OVFL BIT AND A OVFL BIT PRE-INSTRUCTION EXCEPTION
; PRE-EXCEPTION WILL BE TAKEN AT FMOVE.L FPSR,D1 IN CK_FPSTAT ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 23
MOVEQ.L #EB_OVFL,D0 ;SET BIT TST FOR OVERFLOW BIT
BSR SET_FPCR_BIT ;ENABLE OVERFLOW EXCEPTION
FMOVE.X BIGNO(PC),FP3 ;MOVE IN AN ALMOST OVERFLOW NUMBER
FMUL.X BIGNO(PC),FP3 ;CAUSE OVERFLOW
TST.B d5 ;UNEXPECTED EXCEPTION
BNE FAIL ;YES FAILED
MOVEQ.L #FOVFL,D7 ;SET EXPECTED EXCEPTION VECT #
;EXCEPTION WILL OCCUR IN FOLLOWING ROUTINE
BSR CK_FPSTAT ;IS OVFL BIT SET
BEQ FAIL ;NO FAIL
CMPI.B #1,d5 ;DID EXPECTED EXCEPTION OCCUR
BNE FAIL
CLR.L d5 ;CLEAR EXCEPTION OCCURRED FLAG
;DON'T DISABLE OVFL EXCPT YET
;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST STATUS REG OVFL BIT (MOVING TOO LARGE A NUMBER TO MEMORY FOR DATA TYPE)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; THIS TEST WILL TEST THE OVFL BIT AND A OVFL BIT MID-INSTRUCTION EXCEPTION
; DURING EXECUTION OF FMOVE.S FP3,(A4)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 24
FMOVE.X EXTNO(PC),FP3 ;LOAD AN EXTENDED NUMBER
TST.B d5 ;DID UNEXPECTED EXCEPTION OCCUR
BNE FAIL ;YES, FAILED
;MID-INSTRUCTION EXCEPT SHOULD OCCUR DURING FOLLOWING INSTRUCTION
FMOVE.S FP3,(A4) ;CAUSE OVERFLOW
CMPI.B #1,d5 ;DID EXPECTED EXCEPTION OCCUR
BNE FAIL ;NO, FAILED
BSR CK_FPSTAT ;IS OVFL BIT SET
BEQ FAIL ;NO, FAILED
CLR.L d5 ;CLEAR EXCEPTION PASS/FAIL FLAG
CLR.L D7 ;SET VECT# FOR NO EXPECTED EXCEPTS.
FMOVE.L D7,FPCR ;DISABLE ALL FPC EXCEPTIONS
;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST STATUS REG UNFL BIT
;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 25
MOVEQ.L #EB_UNFL,D0 ;SET TEST BIT FOR UNDERFLOW BIT
FMOVE.X SMALLNO(PC),FP4 ;LOAD AN ALMOST UNDERFLOW NUMBER
FMUL.X SMALLNO(PC),FP4 ;CAUSE UNDERFLOW
BSR CK_FPSTAT ;DID UNDERFLOW (UNFL) BIT SET
BEQ FAIL ;NO, FAILED
TST.B d5 ;DID UNEXPECTED EXCEPTION OCCUR
BNE FAIL ;YES, FAILED
;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST STATUS REG INEX2 BIT
;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 26
MOVEQ.L #EB_INEX2,D0 ;SET TEST BIT TO INEX2
FMOVE.X MULOPRND(PC),FP5 ;LOAD AN ALMOST UNDERFLOW NUMBER
FMUL.X TINYNO(PC),FP5 ;CAUSE AN INEXACT RESULT
BSR CK_FPSTAT ;IS INEX2 SET
BEQ FAIL ;NO, FAILED
TST.B d5 ;DID UNEXPECTED EXCEPTION OCCUR
BNE FAIL ;YES, FAILED
;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST STATUS REG OPER BIT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; THIS TEST WILL TEST THE OPER BIT AND A OPER BIT PRE-INSTRUCTION EXCEPTION
; PRE-EXCEPTION WILL BE TAKEN AT FMOVE.L FPSR,D1 IN CK_FPSTAT ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 27
MOVEQ.L #EB_OPERR,D0 ;SET BIT TST FOR OPERAND ERROR
BSR SET_FPCR_BIT ;ENABLE OPERRAND ERROR EXCEPTION
;THE FOLLOWING INSTRUCTION WILL CAUSE A PENDING PRE-INSTRUCTION EXCEPTION
FSQRT.X MINUS_X(PC),FP6 ;CAUSE AN OPERAND ERROR
TST.B d5 ;DID UNEXPECTED EXCEPTION OCCUR
BNE FAIL ;YES, FAILED
MOVEQ.L #FOPERR,D7 ;EXPECTED EXCEPTION #
;EXCEPTION WILL OCCUR IN THE FOLLOWING ROUTINE
BSR CK_FPSTAT ;IS OPER BIT SET
BEQ FAIL ;NO, FAIL
CMPI.B #1,d5 ;DID EXPECTED EXCEPTION OCCUR
BNE FAIL ;NO, FAILED
CLR.L d5 ;CLEAR EXCEPTION PASS/FAIL FLAG
CLR.L D7 ;SET EXCEPT VECT # TO NONE EXPECTED
FMOVE.L D7,FPCR ;DISABLE ALL FPC EXCPTIONS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TEST FTRAPcc USING FTRAPEQ
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADDQ.W #1,d6 ;SUBTEST # 28
FMOVECR.X #$0C,FP0 ;GET e CONSTANT
FTEQ ;TRAP SHOULD NOT OCCUR
TST.B d5 ;DID UNEXPECTED TRAP OCCUR
BNE FAIL ;YES, FAILED
MOVEQ.L #TRAP,D7 ;EXPECTED TRAP VECTOR #
FMOVECR.X #$0F,FP1 ;GET 0.0 CONSTANT
FTEQ ;SHOULD TAKE TRAP
CMPI.B #1,d5 ;DID EXPECTED TRAP OCCUR
BNE FAIL ;NO, FAILED
CLR.L d5 ;CLEAR EXCEPTION PASS/FAIL FLAG
CLR.L D7 ;SET VECT# FOR NO EXPECTED EXCEPTS.
FMOVE.L D7,FPCR ;DISABLE ALL FPC EXCEPTIONS
;TEST SOME MATH INSTRUCTIONS
; 2 * PI = PI + PI
ADDQ.W #1,d6 ;SUBTEST # 29
FMOVECR.X #0,FP0 ;GET PI FROM ROM
FMOVE.X FP0,FP1
FADD.X FP1,FP0
FMUL.X #"2.0",FP1
FCMP.X FP0,FP1 ;DOES 2*PI = PI+PI
FBNE FAIL
TST.B d5 ;ANY UNXPECTED EXCEPTIONS
BNE FAIL
; SIN (PI/3) = COS (PI/6) = (SQRT 3) / 2
ADDQ.W #1,d6 ;SUBTEST # 30
FMOVECR.X #0,FP0 ;GET PI
FMOVE.X FP0,FP1 ;AND AGAIN
FMOVE.X ONE_X(PC),FP2 ;GET 1.0
FMOVE.X FP2,FP3 ;
FDIV.X #"3.0",FP2 ;CALCULATE 1/3
FDIV.X #"6.0",FP3 ;""""""""" 1/6
FMUL.X FP2,FP0 ; 1/3 * PI
FMUL.X FP3,FP1 ; 1/6 * PI
FSIN.X FP0 ; SIN (1/3 * PI)
FCOS.X FP1 ; COS (1/6 * PI)
;CONVERT VALUES TO SINGLE PRECISION TO GET RID OF ROUND-OFF ERROR
FMOVE.S FP0,D0
FMOVE.S FP1,D1
FMOVE.S D0,FP0
FMOVE.S D1,FP1
FCMP.X FP0,FP1 ; IS SIN(1/3 * PI) = COS(1/6 * PI)
FBNE FAIL
FSQRT.X #"3.0",FP4 ;GET SQRT OF 3
FDIV.X #"2.0",FP4 ;DIVIDE IT BY 2
;CONVERT VALUES TO SINGLE PRECISION TO GET RID OF ROUND-OFF ERROR
FMOVE.S FP4,D2
FMOVE.S D2,FP4
FCMP.X FP1,FP4 ;ARE THEY BOTH = (SQRT 3) / 2
FBNE FAIL ;NO, FAILED
TST.B d5 ;ANY UNEXPECTED EXCEPTIONS
BNE FAIL
;TAN (PI/4) = SIN (PI/2)
ADDQ.W #1,d6 ;SUBTEST # 31
FMOVE.X ONE_X(PC),FP5 ;GET 1.0
FMOVE.X FP5,FP0 ;SAVE FOR LATER
FMOVECR.X #0,FP6 ;GET PI
FDIV.X #"4.0",FP5 ;1/4
FMUL.X FP6,FP5 ;1/4 * PI
FTAN.X FP5 ;TAN (PI/4)
FDIV.X #"2.0",FP0 ;1/2
FMUL.X FP6,FP0 ;1/2 * PI
FSIN.X FP0 ;SIN (PI/2)
;CONVERT VALUES TO SINGLE PRECISION TO GET RID OF ROUND-OFF ERROR
FMOVE.S FP0,D0
FMOVE.S FP5,D1
FMOVE.S D0,FP0
FMOVE.S D1,FP5
FCMP.X FP0,FP5 ;IS TAN (1/4 * PI) = 1.0
FBNE FAIL ;NO, FAILED
TST.B d5
BNE.S FAIL
;LOG 10 OF 0.01 = -2 AND 10 RAISED TO -2 = 0.01
ADDQ.W #1,d6 ;SUBTEST # 32
FMOVE.X #"0.01",FP0
FMOVE.X FP0,FP1
FLOG10.X FP1 ;LOG 10 OF 0.01 = -2
FTENTOX.X FP1 ;10 RAISED TO -2 = 0.01
;CONVERT VALUES TO SINGLE PRECISION TO GET RID OF ROUND-OFF ERROR
FMOVE.S FP0,D0
FMOVE.S FP1,D1
FMOVE.S D0,FP0
FMOVE.S D1,FP1
FCMP.X FP0,FP1 ;DID YOU END UP WHERE YOU STARTED
FBNE FAIL
TST.B d5 ;UNEXPECTED EXCEPTION ?
BNE.S FAIL
;IF HERE THEN MUST HAVE PASSED ALL THE TESTS SO RTN PASSED
; CHANGED FOLLOWING FROM .W TO .L
move.l d6,d0 ;Remember how far we got <26>
clr.l d6 ;and clear the status register <26>
bra.s FPUFinish ;then go finish up <26>
FAIL move.l d6,d0 ;Place the error in d0 <26>
;IF FPU WAS PRESENT I.E. SUBTEST # IS GREATER THAN # 3
;THEN RE-INIT FPU ELSE SKIP
FPUFinish CLR.L D2 ;GET D2 READY FOR COPROC FLAG <26>
CMP.b #2,d0 ;IF SUBTEST # <= 2 THEN FPU NOT PRESENT <26>
BLS.S @NO_FPU ;OR EARLY ERROR SO SKIP FPU RE-INIT
; SOFTWARE RESET OF FLOATING-POINT COPROCESSOR
LEA.L READ_STR(A6),A2 ;GET SOME STACK SPACE
CLR.L -(A2) ;SET FORMAT WORD TO NULL
FRESTORE (A2)+ ;FPC SOFTWARE RESET
; GET NULL STATE FRAME FROM FLOATING-POINT COPROC TO DETERMINE WHETHER IT IS 68881 OR 68882
FSAVE -(A2) ;GET NULL STATE FRAME
MOVE.W #$01,D2 ;SET COPROC FLAG FOR 68881 FLAG = 1
MOVE.B 1(A2),D1 ;GET STATE FRAME SIZE TO DETERMINE 881 OR 882
CMPI.B #$18,D1 ;IS IT 68881
BEQ.S @FL881 ;YES, BRANCH
ADD.W #$01,D2 ;NO, INDICATE THAT IT'S A 68882 FLAG = 2
@FL881 SWAP D2 ;GET FLAG INTO UPPER WORD OF D2
@NO_FPU OR.L D2,D0 ;PUT COPROC TYPE IN HIWORD AND PASS/FAIL IN LOWORD
; MOVED RESTORATION OF VBR TO SYSTEM EXCEPTION TABLE TO HERE
MOVEA.L A5,A0 ;GET ORIGINAL VBR PTR
MOVEC.L A0,VBR ;RESTORE OS VBR
UNLK A6 ;DE-ALLOCATE LOCAL STORAGE
movem.l (sp)+,d2/d7 ;restore regs <26>
cmp.b #2,d6 ;Was this an FPU not present error? <26>
bne.s @FPUrtn ;go ahead and return if not <26>
move.w d2,d1 ;Else get the box flag <26>
lsr.w #8,d1 ;get it in lsb <26>
lea.l @FPUOptnBox,a0 ;table of boxes for which the FPU is optional <26>
@OptnLoop move.b (a0)+,d3 ;get a boxflag <26>
cmp.b #boxUnknown,d3 ;is this the end of the table? <26>
beq.s @FPUrtn ;return now if so - FPU should be there <26>
cmp.b d3,d1 ;else is this a machine with an optional FPU? <26>
bne.s @OptnLoop ;keep looking if not <26>
moveq.l #-1,d6 ;optional FPU - test probably does not apply <26>
@FPUrtn MOVE.W (SP)+,SR ;RESTORE CALLER'S INTERRUPTS <26>
RTS6 ;RTN TO CALLER <26>
;
;The following table contains a list of the box flags for which an FPU <26>
;is optional <26>
;
@FPUOptnBox dc.b BoxMacIIsi ; <29>
dc.b BoxMacLC ; <29>
dc.b BoxMacLCII ; <SM5>
dc.b boxPowerBook170 ; <H7>
dc.b boxPowerBookDuo210 ; <H10>
dc.b boxPowerBookDuo230 ; <H10>
dc.b boxPowerBookDuo250 ; <SM15>
dc.b boxDBLite20 ; <SM15>
dc.b boxLCIII ; <H11><SM6><SM13>
dc.b boxVail16 ; <H11><SM6>
dc.b boxCentris610 ; <H14><SM6><SM13>
dc.b boxQuadra610 ; <H14><SM6><SM13>
dc.b boxWombat20 ; <H14><SM6>
dc.b boxCentris650 ; <26><H14><H15><SM6><SM13>
IF forSmurf THEN ; <SM14>
dc.b boxRiscCentris650 ; <SM12>
ENDIF
dc.b boxPrimus20 ; <SM13>
dc.b boxLC475 ; <SM13>
dc.b boxAladdin20 ; <SM13>
dc.b boxQuadra605 ; <SM13>
dc.b boxOptimus20 ; <SM13>
dc.b boxOptimus25 ; <SM13>
dc.b boxLC575 ; <SM13>
dc.b boxUnknown ; end of table <H15>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; CK_FPSTAT: WILL TEST A SELECTED BIT IN THE FPSR (FLOATING-POINT
; STATUS REGISTER) AND RETURN IT'S STATUS
;
; ENTRY: D0.L = BIT LOCATION TO TEST
;
; EXIT: IF BIT SET
; CCR Z=0
; ELSE
; CCR Z=1
;
; ALTERED: D1.L
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
CK_FPSTAT FMOVE.L FPSR,D1 ;GET FPC STATUS REG
BTST.L D0,D1 ;GET BIT STATUS
RTS ;RTN BIT STATUS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; SET_FPCR_BIT: WILL SET A SPECIFIC BIT IN THE FPCR
;
; ENTRY: D0.L = BIT NUMBER TO BE SET
;
; EXIT: D1.L = NEW FPCR VALUE
;
; ALTERED: D1.L
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SET_FPCR_BIT
FMOVE.L FPCR,D1 ;GET EXISTING FPCR
BSET.L D0,D1 ;SET DESIRED BIT
FMOVE.L D1,FPCR ;WRITE NEW FPCR VALUE BACK TO FPCR
RTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; VER_DAT: WILL VERIFY DATA WRITTEN TO AND READ FROM FLOATING-POINT CP
;
; ENTRY: A0.L = PTR TO EXPECTED DATA
; -2(A0) = NUMBER OF BYTES IN DATA
; A4.L = PTR TO ACTUAL DATA READ FROM FPC
;
; EXIT: IF NO MISMATCHES (SUCCESSFUL)
; Z = 1
; ELSE
; Z = 0
;
; ALTERED: NONE
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
VER_DAT MOVEM.L A4/D0,-(SP) ;SAVE
MOVE.W -2(A0),D0 ;GET NUMBER OF BYTES IN DATA
SUBQ.W #1,D0 ;ADJUST FOR DBNE INST
VD1 CMP.B (A0)+,(A4)+ ;WRITTEN DATA = READ DATA
DBNE D0,VD1 ;YES, TEST ANOTHER OR COUNT OUT
BEQ.S VD2 ;BRANCH IF ALL BYTES MATCHED
MOVEQ.L #1,D0 ;CLEAR Z FLAG FOR FAILURE
VD2 MOVEM.L (SP)+,A4/D0 ;RESTORE
RTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; FPC_EHND: WILL HANDLE MOST FLOATING-POINT RELATED EXCEPTIONS
; EXPECTED OR NOT. WILL INDICATE AN EXCEPTION ERROR
; IF THE EXCEPTION WAS NOT EXPECTED OR IF THE EXCEPTION
; TAKEN DOES NOT MATCH THE EXCEPTION EXPECTED.
;
; ENTRY: IF D7.B > 0 THEN
; EXCEPTION IS EXPECTED (INTENTIONAL)
; ELSE
; EXCEPTION IS UNEXPECTED (UNINTENTIONAL)
;
; EXIT: IF d5.B = 1
; EXCEPTION WAS EXPECTED, AND EXCEPTION TAKEN
; IS THE SAME AS EXCEPTION EXPECTED (VECTOR #'S MATCH)
; ELSE
; d5.B = 2
; UNEXPECTED EXCEPTION OR WRONG EXCEPTION OCCURRED
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FPC_EHND MOVE.L D0,-(SP) ;SAVE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FSAVE -(SP) ;SAVE STATE INFO FOR 68882
MOVE.B (SP),D0 ;GET FIRST BYTE OF STATE FRAME
BEQ NULL ;BRANCH IF NULL FRAME
CLR.L D0 ;
MOVE.B 1(SP),D0 ;GET STATE FRAME SIZE
BSET.B #3,(SP,D0) ;SET BIT 27 OF BIU (SO YOU WON'T GET INFINITE EXCEPTION LOOP)
NULL FRESTORE (SP)+ ;RESTORE STATE INFO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOVEQ.L #1,d5 ;EXCEPTION OCCURRED
TST.B D7 ;WAS EXCEPTION EXPECTED
BEQ.S FE1 ;NO, BRANCH
MOVE.W 10(SP),D0 ;GET VECTOR OFFSET AND FORMAT
AND.W #$FFF,D0 ;MASK FORMAT
LSR.W #2,D0 ;CONV OFFSET TO VECTOR NUMBER
CMP.B D7,D0 ;DO VECTOR NUMBERS MATCH
BEQ.S FE2 ;YES BRANCH
FE1 MOVEQ.L #2,d5 ;NO, INDICATE EXCEPTION ERROR
FE2 MOVE.L (SP)+,D0 ;RESTORE
RTE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; PM_EXCPT: WILL HANDLE THE FOLLOWING PRE AND MID-INSTRUCTION EXCEPTIONS
; F-LINE, COPROCESSOR PROTOCOL VIOLATION
; FORMAT ERROR, PRIVILEGE VIOLATION
;
; ENTRY: IF EXCEPTION IS EXPECTED
; D7.B = VECTOR # OF EXPECTED EXCEPTION
; A0.L = NEW RETURN ADDRESS TO BE PLACED IN STACK
; ELSE
; D7.B = 0
;
; EXIT: IF EXCEPTION WAS EXPECTED
; STACK RETURN ADDRESS IS ALTERED APPROPRIATELY
; FOR FOUR WORD PRE-INST OR 10 WORD MID-INST STACK
; d5.L = 1
; ELSE
; STACK IS CLEANED APPROPRIATELY
; d6.W = d6.W + $1000 TO INDICATE UNEXPECTED EXCEPTION
; BRANCHES TO "FAIL" DIRECTLY TO REPORT ERROR AND END TEST
;
; POSSIBLY ALTERED: D0.W, D1.L, d6.W, d5.L,
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PM_EXCPT
MOVEQ.L #1,d5 ;EXCEPTION POINTING HERE OCCURRED
MOVEQ.L #10,D1 ;INIT SHIFT COUNT FOR GETTING STACK FORMAT
MOVE.W 6(SP),D0 ;GET FORMAT AND VECTOR OFFSET
LSR.W #2,D0 ;CVT OFFSET TO VECTOR #
CMP.B D0,D7 ;DID EXPECTED EXCEPTION OCCUR
BNE.S PE1 ;NO, BRANCH
LSR.W D1,D0 ;GET STACK FORMAT
TST.B D0 ;IS THIS 4-WORD PRE-INST STACK
BNE.S PE2 ;NO, BRANCH
MOVE.L A0,2(SP) ;YES, THEN ADJUST RTN ADDRESS IN STACK
BRA.S PE3 ;
PE2 MOVE.L A0,8(SP) ;ADJUST RTN ADDRESS FOR 10 WORD MID INST STACK
PE3 RTE ;RETURN FROM EXCEPTION
;HERE IF UNEXPECTED EXCEPTION
PE1 LSR.W D1,D0 ;GET STACK FORMAT
TST.B D0 ;IS IT 4 WORD PRE-INST STACK
BNE.S PE4 ;NO, BRANCH
ADDQ.L #8,SP ;SP=SP+8 CLEANS STACK
BRA.S PE5
PE4 ADDA.L #20,SP ;SP=SP+20 CLEANS 10 WORD STACK
PE5 ADDI.W #$1000,d6 ;INDICATE UNEXPECTED EXCEPTION IN SUBTEST #
; NOW JUMP TO END OF TEST TO REPORT FAILURE
BRA FAIL
; TEST DATA
XDENORM DC.W $0000,$0000,$7FFF,$FFFF,$FFFF,$FFFF
BIGNUM DC.W $7FFD,$0000,$E35F,$A931,$A000,$0000
SMALLNUM DC.W $9001,$0000,$ABCC,$7711,$8461,$CEFD
SGLNAN DC.W $7FFF,$0000,$00A0,$A0A0,$0000,$0000
ZERO_X DC.X "0.0"
ONE_X DC.X "1.0"
MINUS_X DC.X "-1.0"
EXTNO DC.W $7FFE,$0000,$89AB,$CDEF,$0123,$4567
BIGNO DC.W $7FFE,$0000,$8000,$1020,$0000,$0000
SMALLNO DC.W $0002,$0000,$8000,$0001,$0000,$0000
MULOPRND DC.W $3FFF,$0000,$C000,$0000,$0001,$73A1
TINYNO DC.W $3FFF,$0000,$8000,$0000,$0000,$0001
;TEST DATA FORMAT FOR FOLLOWING DATA (FOR EACH DATA SET):
; DC.W # OF BYTES THAT FOLLOW
; DC.n DATA ITSELF, IN SPECIFIED FORMAT
DC.W 12
FREMRSLT DC.W $9000,$0000,$A0AC,$F842,$FB63,$6FFC
;NAN I.E. NOT A NUMBER
DC.W 12
NAN DC.B $7F,$FF,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DC.W 4
MOVLNGCR DC.L 0
DC.W 4
MOVLNG1 DC.L $55555555
DC.W 4
MOVLNG2 DC.L $AAAAAAAA
DC.W 2
MOVWD DC.W $5555
DC.W 1
MOVBT DC.B $AA
DC.W 4
MOVSGL DC.S "123456789.123456789"
DC.W 8
MOVDBL DC.D "123456789123456789.123456789123456789"
DC.W 12
;MOVEXT DC.X "123456789123456789123456789.123456789123456789123456789"
;NOTE THAT THE FOLLOWING MOVEXT DEFINITION IS A MODIFIED REPRESENTATION
;OF THE ABOVE MOVEXT DEFINITON. THE FOLLOWING WAS NECESSARY BECAUSE THE
;ASSEMBLER DOES NOT TREAT THE EXTENDED PRECISION ZERO BITS AS ZERO, BUT
;THE FLOATING-POINT CP WILL WRITE THEM AS ZERO.
MOVEXT DC.W $4055,$0000,$CC3D,$FBE5,$C763,$3EF5
MOVEXT2 DC.W 12
DC.X "0.0"
MOVBCDW DC.P "1.2345678765E+4"
DC.W 12
MOVBCDSR DC.P "1.23E+4"
DC.W 12
MOVBCDDR DC.P "1.234567877E+4"
DC.W 12
PI DC.P "3.1415927E+0"
DC.W 24
;MOVMEXT DC.X "123456789123456789123456789.123456789123456789123456789"
;NOTE THAT THE FOLLOWING MOVMEXT DEFINITION IS A MODIFIED REPRESENTATION
;OF THE ABOVE MOVEXT DEFINITON. THE FOLLOWING WAS NECESSARY BECAUSE THE
;ASSEMBLER DOES NOT TREAT THE EXTENDED PRECISION ZERO BITS AS ZERO, BUT
;THE FLOATING-POINT CP WILL WRITE THEM AS ZERO.
MOVMEXT DC.W $4055,$0000,$CC3D,$FBE5,$C763,$3EF5
DC.X "0.0"
move.l #-1,d6 ;load fail/no-log code <v1.7>
jmp (a6) ;return to caller <v1.7>
TestPGC
;-------------------------------------------------------------------------------
; Routine: #8E: TestPGC
;
; Inputs: a0 - ptr to table of hardware base addresses
; d0 - bit mask indicating which base addresses are valid
; d2 - boxflag/decoder type
; a6 - return address
;
; Outputs: d6 - 0 if test passes, fail code otherwise
;
; Destroys:
;
; This routine will test the Parity Generator Chip on Aurora, if parity RAM is
; installed.
;
; Note that this test assumes that the parity bit in d7 is set. This assumption <25>
; is only valid during startup diagnostics. If this test is run from the serial <25>
; test manager or the _TestManager trap, the parity bit in d7 is not guaranteed <25>
; to be set properly. (Of course, this is a destructive test so you shouldn't <25>
; run it from the _TestManager trap anyway). <25>
;
;-------------------------------------------------------------------------------
btst.l #DecoderInfo.RBVExists,d0 ;<25>
beq.s @exit
btst #parity,d7 ;is parity ram installed?
beq.s @exit ;no, don't run pgc test
move.l DecoderInfo.VIA1Addr(a0),a2 ;Get VIA1 base address (used by NMI)
move.l DecoderInfo.RBVAddr(a0),a3 ;Get RBV base address <21>
move.l a6,-(sp) ;save return address
movea.l a7,a5 ;mark sp for NMI handler
bset #beok,d7 ;tell the bus error handler it's ok
move.l #PGCParity,d0 ;tell the NMI handler to expect errors
moveq #32-1,d5 ;loop counter
moveq #1,d4 ;test value
lea -4(sp),a4 ;grab a long from the stack
bclr #vPGCEnb,VBufB(a2) ;enable parity checking
@step1
lea @step2,a6 ;NMI here means parity error (expected)
bclr #RvPGCTest,VBufB(a3) ;switch to even parity for writes
tst.b (a2) ;access VIA to delay a bit
move.l d4,(a4) ;write test word with even parity
tst.l (a4) ;read (with odd parity), should get an error
bra.s @error ;no NMI, somethings wrong
@step2
lea @step3,a6 ;NMI here means parity error (expected)
bset #RvPGCTest,VBufB(a3) ;generate normal (odd) parity
tst.b (a2) ;access VIA to delay a bit
tst.l (a4) ;read, shouldn't get error here either
bra.s @error ;no NMI, somethings wrong
@step3
lea @error,a6 ;NMI here means parity error
move.l d4,(a4) ;write test word with odd parity
tst.l (a4) ;read word, shouldn't have parity error
rol.l #1,d4 ;check next bit
dbra d5,@step1
moveq.l #0,d6 ;signal all's well
bra.s @good ;parity ok, exit with it enabled
@error move.l #parityErr,d6 ;signal we got a parity error
bset #vPGCEnb,VBufB(a2) ;disable parity checking
bset #RvPGCTest,VBufB(a3) ;generate normal (odd) parity
tst.b (a2) ;access VIA to delay a bit
@good
moveq.l #0,d0 ;clear the parity signature
bclr.l #beok,d7 ;clear the bus error OK flag
rts ;return to caller
@exit moveq #-1,d6 ;load fail/no-log code
RTS6 ;return to caller
;----------------------------------------------------------------------
; #8F: FMCRegTest - Walk ones across the shift register
;
; Inputs: a0 - ptr to table of hardware base addresses
;
; Outputs: d6.u - expected value (zero if pass)
; d6.l - actual value (zero if pass)
;
; Register Usage: d0-d2,d6,a0,a5-a6
;
;----------------------------------------------------------------------
FMCRegTest
btst.l #DecoderInfo.FMCExists,d0 ;do we have an FMC? <21>
beq FMCRegAbort ;no, so quit
move.l a6,a5 ;save return address
move.l DecoderInfo.FMCAddr(a0),a0 ;get base address of FMC <21>
clr.l d6 ;clear pattern register
BSR6 ReadFMCShiftReg ;read current value of shift register
move.w d0,d2 ;save original value for restoration later
@nextValue
move.w d6,d0 ;move pattern into passing register
BSR6 WriteFMCShiftReg ;write the pattern
move.l @Busfloat,d0 ;do something to get the data bus to float
bra.s @continue ;continue
@Busfloat
dc.l $FFFFFFFF ;make the data bus float
@continue
BSR6 ReadFMCShiftReg ;read what we just wrote
cmp.w d0,d6 ;compare it to expected pattern
bne.s @fail ;if not the same then squawk
cmp.w #$FFFF,d6 ;has last pattern been tested?
beq.s @testPass ;yes, so finish up
asl.w #1,d6 ;no, so shift left
ori.w #1,d6 ; and set a one
bra.s @nextValue ;continue
@testPass
clr.l d6 ;test passed, so clear error code
bra.s @FMCRegTestEnd ;quit
@fail
swap d6 ;else put expected pattern in upper word
move.w d0,d6 ; and put actual pattern in lower word
@FMCRegTestEnd
move.w d2,d0 ;get original shift reg value
BSR6 WriteFMCShiftReg ;restore it
;(if we failed, this obviously may not work!)
move.l a5,a6 ;restore return address
RTS6 ;return
;----------------------------------------------------------------------
; WriteFMCShiftReg
;
; Inputs: a0 - FMC base address
; d0 - pattern to write to shift register
;
; Outputs: none
;
; Register Usage: d0-d1,a0,a6
;----------------------------------------------------------------------
WriteFMCShiftReg
moveq #15,d1 ;init loop count
@1 move.b d0,(a0) ;move bit 0 into FMC config reg
ror.w #1,d0 ;rotate next bit into place
dbra d1,@1 ;continue
RTS6 ;return
;----------------------------------------------------------------------
; ReadFMCShiftReg
;
; Inputs: a0 - FMC base address
;
; Outputs: d0 - pattern read from shift register
;
; Register Usage: d0-d1,a0,a6
;----------------------------------------------------------------------
ReadFMCShiftReg
clr.l d0 ;init return value
moveq #15,d1 ;init loop count
@1 move.b (a0),d0 ;move bit 0 from FMC config reg
ror.l #1,d0 ;rotate into upper word
dbra d1,@1 ;continue
swap d0 ;move pattern into lower word
RTS6
FMCRegAbort
moveq #-1,d6 ;load fail/no-log code
RTS6 ;return to caller
;------------------------------------------------------------------------------- <3>
;
; #90: FMC/Cache test using the OSS's ROM Control Bit
;
; Inputs: a0 - ptr to table of hardware base addresses
;
; Outputs: d6 - error code
;
; Destroys: d0-d3/a2-a4
; d3 - temp. for block move and compare.
; d4 - saved cacr.
; d5 - loop index.
;
; Called by BSR6
;------------------------------------------------------------------------------- <3>
sizeOfExternalCache equ 32*1024
blockAddr equ 32*1024
ramBlockPtr equ A2
romBlockPtr equ A3
ossBasePtr equ A4
temp equ D3
savedCACR equ D4
loopIndex equ D5
enableInstructionCache equ 1<<0
clearInstructionCache equ 1<<3
instructionBurstEnable equ 1<<4
enableDataCache equ 1<<8
clearDataCache equ 1<<11
dataBurstEnable equ 1<<12
OSSMap1Bit equ 3
FMCCacheTest ; <3>
btst.l #DecoderInfo.FMCExists,d0 ;do we have an FMC? <21>
beq FMCCacheAbort ;no, so quit
; Get the addresses of both a RAM block and a ROM block.
; Both blocks will have the same offsets from the base of RAM and ROM repectively
; so that the ROM block will map into the RAM block when ROM is mapped into the
; RAM space.
; Get the address of the OSS chip for use later.
move.l #blockAddr,ramBlockPtr ; RAM block address.
lea.l ($40000000,ramBlockPtr),romBlockPtr ; ROM block address (this will map to the RAM block address).
move.l DecoderInfo.OSSAddr(a0),ossBasePtr ; Get OSS base. <21>
; Save the state of the cache configuration.
movec cacr,savedCACR
; Enable the internal instruction cache.
; Disable bursting on the internal instruction cache.
; Enable the internal data cache.
; Enable bursting on the internal data cache.
; Flush both internal data caches.
move.l #(enableDataCache+dataBurstEnable+clearDataCache+enableInstructionCache+clearInstructionCache),d1
movec d1,cacr
;
; Part 1
;
; Read an arbitrary block of ROM, effectively flushing the external cache
; of all RAM block and ROM block locations.
move.l #sizeOfExternalCache,loopIndex
@loop0
sub.l #4,loopIndex
bmi.s @endLoop0
tst.l (sizeOfExternalCache,romBlockPtr,loopIndex.l)
bra.s @loop0
@endLoop0
; Initialize the RAM block to the complement of the corresponding ROM block.
move.l #sizeOfExternalCache,loopIndex
@loop1
sub.l #4,loopIndex
bmi.s @endLoop1
move.l (romBlockPtr,loopIndex.l),temp
not.l temp
move.l temp,(ramBlockPtr,loopIndex.l)
bra.s @loop1
@endLoop1
; Map ROM down at address $00000000.
bclr #OSSMap1Bit,OSSRomCntl(ossBasePtr)
; Flush the internal data cache so that all reads will burst in from
; RAM space (we're actually reading ROM though, remember!).
; or.l #clearDataCache,d1
; movec d1,cacr
; Read the entire block, this should fill the cache with data
; from ROM.
move.l #sizeOfExternalCache,loopIndex
@loop2
sub.l #4,loopIndex
bmi.s @endLoop2
tst.l (ramBlockPtr,loopIndex.l)
bra.s @loop2
@endLoop2
; Disable the internal data cache.
and.l #~(enableDataCache+dataBurstEnable),d1
movec d1,cacr
; Unmap ROM from address $00000000.
bset #OSSMap1Bit,OSSRomCntl(ossBasePtr)
; Read the block and compare it to the corresponding ROM block.
; Data read from the external cache should match the ROM block (Good!).
; Data read from ram should not match the ROM block (Bad!).
; If the data does not match, then clean up and exit FAILED.
move.l #sizeOfExternalCache,loopIndex
@loop3
sub.l #4,loopIndex
bmi.s @endLoop3
move.l (romBlockPtr,loopIndex.l),temp
cmp.l (ramBlockPtr,loopIndex.l),temp
bne @failPart1
bra.s @loop3
@endLoop3
;
; Part 2
;
; Again, initialize the block to the complement of the corresponding ROM block.
; This time since the block addresses are cached, were writing to the cache
; RAM as well as to system RAM.
move.l #sizeOfExternalCache,loopIndex
@loop4
sub.l #4,loopIndex
bmi.s @endLoop4
move.l (romBlockPtr,loopIndex.l),temp
not.l temp
move.l temp,(ramBlockPtr,loopIndex.l)
bra.s @loop4
@endLoop4
; Map ROM down at address $00000000.
bclr #OSSMap1Bit,OSSRomCntl(ossBasePtr)
; Read the block and compare it to the corresponding ROM block.
; Data read from the external cache should match complement of the ROM block (Good!).
; Data read from the low memory mapped ROM image should NOT match
; the complement of the ROM block (Bad!).
; If the data does not match, then clean up and exit FAILED.
move.l #sizeOfExternalCache,loopIndex
@loop5
sub.l #4,loopIndex
bmi.s @endLoop5
move.l (romBlockPtr,loopIndex.l),temp
not.l temp
cmp.l (ramBlockPtr,loopIndex.l),temp
bne.s @failPart2
bra.s @loop5
@endLoop5
@passed
clr.l d6
bra.s @CleanUp
@failPart1
move.l #$10000000,d6
bra.s @failCommon
@failPart2
move.l #$20000000,d6
; bra.s @failCommon
@failCommon
move.w loopIndex,d6 ; Put the block offset into d6.
bra.s @CleanUp
nop
; CLEAN UP
; Unmap ROM from address $00000000.
; Enable bursting on the internal data cache.
; Read then write the block so that the data in the cache is the same as that in RAM.
; Restore the state of the cache configuration.
@CleanUp
bset #OSSMap1Bit,OSSRomCntl(ossBasePtr)
or.l #(enableDataCache+dataBurstEnable+clearDataCache),d1
movec d1,cacr
move.l #sizeOfExternalCache,loopIndex
@loop6
sub.l #4,loopIndex
bmi.s @endLoop6
tst.l (ramBlockPtr,loopIndex.l)
clr.l (ramBlockPtr,loopIndex.l)
bra.s @loop6
@endLoop6
movec savedCACR,cacr
RTS6
FMCCacheAbort ; <3>
moveq #-1,d6 ;load fail/no-log code
RTS6 ;return to caller
;----------------------------------------------------------------------
; #91: OSSRegTest - count down thru all possible values for registers:
; - Interrupt Mask Registers
; - ROM Control register (except bit 7)
; - System Counter Control Register
; (see table below for step # correspondence)
;
; Inputs: a0 - ptr to table of hardware base addresses
;
; Outputs: d6.u - step number
; d6.l - failed bit mask
;
; Register Usage: d0-d6,a0-a1,a6
;
;----------------------------------------------------------------------
OSSRegTest
btst.l #DecoderInfo.OSSExists,d0 ;do we have an OSS? <21>
beq OSSRegAbort ;no, so quit
move.w sr,d5 ;save old status
ori.w #$700,sr ;mask out all interrupts
move.l DecoderInfo.OSSAddr(a0),a0 ;get base address of OSS <21>
lea OSSRegToTest,a1 ;get ptr to table
clr.l d6 ;clear results/step register
@nextReg
clr.l d0 ;clear test value
move.l (a1)+,d2 ;get the register info
beq.s @pass ;last entry in table so tests pass
move.w d2,d4 ;else save bit mask/max value
swap d2 ; and put offset in lower word
move.b (a0,d2.w),d3 ;save original value
@nextValue
move.b d0,(a0,d2.w) ;move test value into register under test
move.l @Busfloat,d1 ;do something to get the data bus to float
bra.s @continue ;continue
@Busfloat
dc.l $FFFFFFFF ;make the data bus float
@continue
move.b (a0,d2.w),d1 ;get the value just written
ror.w #8,d4 ;rotate mask byte low
and.b d4,d1 ;mask all but bits we're interested in
eor.b d0,d1 ;compare written value to read value
bne.s @fail ;if not the same then squawk
ror.w #8,d4 ;rotate max value byte low
cmp.b d4,d0 ;have we tested the max value yet?
beq.s @currentTestPass ;yes, so continue with next register
addq #1,d0 ;no, so generate next test value
bra.s @nextValue ;go test the next value
@currentTestPass
move.b d3,(a0,d2.w) ;restore original value
addq #1,d6 ;increment step counter
bra.s @nextReg ;do next register
@pass
clr.l d6 ;all tests passed
bra.s @OSSRegTestEnd ;so quit
@fail
move.w d3,(a0,d2.w) ;restore original value
swap d6 ;put step value in upper word
move.w d1,d6 ;put failed bit mask in lower word
@OSSRegTestEnd
move.w d5,sr ;restore old status
RTS6 ;return to caller
;---------------------------------------------------------------------------
; This table contains the offsets, the valid bit mask, and the max value
; the register is to be tested to.
;
; NOTE: This is obviously not the most efficient way for testing the
; IMRs. However, since we want to test a few other registers as well,
; this seems to be the best way to keep the code from becoming to
; convoluted (I think).
;---------------------------------------------------------------------------
OSSRegToTest
dc.w OSSMskSlot9, $0706
dc.w OSSMskSlotA, $0706
dc.w OSSMskSlotB, $0706
dc.w OSSMskSlotC, $0706
dc.w OSSMskSlotD, $0706
dc.w OSSMskSlotE, $0706
dc.w OSSMskPSwm, $0706
dc.w OSSMskPScc, $0706
dc.w OSSMskSnd, $0706
dc.w OSSMskScsi, $0706
dc.w OSSMsk60Hz, $0706
dc.w OSSMskVia1, $0706
dc.w OSSMskRTC, $0706
dc.w OSSMskADB, $0706
dc.w OSSRomCntl, $1F1F ;all but the Pwr bit!
dc.w OSSCntrCntl, $0303
dc.w 0, 0
OSSRegAbort
moveq #-1,d6 ;load fail/no-log code
RTS6 ;return to caller
;----------------------------------------------------------------------
; #92: OSSIntTest - tests the 60Hz interrupt and the IPL lines by
; using a local interrupt handler set at the full range
; of priority levels
;
; Inputs: a0 - ptr to table of hardware base addresses
;
; Outputs: d6 - interrupt level that failed
;
; Register Usage: d0-d2,d5-d6,a0-a3,a6
;
;----------------------------------------------------------------------
OSSIntTest
OssIntSig equ $64656269 ;
btst.l #DecoderInfo.OSSExists,d0 ;do we have an OSS? <21>
beq OSSIntAbort ;no, so quit
move.w sr,d5 ;save old status
; ori.w #$700,sr ;mask out all interrupts
and.w #$F8FF,sr ;enable all interrupts
move.l DecoderInfo.OSSAddr(a0),a0 ;get base address of OSS <21>
lea myIntHandler,a3 ;get local interrupt vector
move.b OSSMsk60Hz(a0),d2 ;save current value of 60Hz IMR
move.b #6,d6 ;keep track of interrupt level
movec VBR,a1 ;
add.l #autoint6,a1 ;start with level 6 vector
@nextLevel
move.l (a1),a2 ;preserve os level 1 vector
move.l a3,(a1) ;and install it
move.b d6,OSSMsk60Hz(a0) ;set interrupt level for 60Hz int
move.w #$8000,d1 ;now let's wait for our interrupt
clr.l d0 ;clear our 'been there' flag
@10 cmp.l #OssIntSig,d0 ;did our handler touch d0?
beq.s @rcvdInterrupt ;yes, so continue with next level
dbra d1,@10 ;no, so wait for timeout
move.b #0,OSSMsk60Hz(a0) ;disable 60Hz interrupt while moving vectors
move.l a2,(a1) ;restore os level 1 vector
bra.s @OSSIntTestEnd ;timeout, level is in d6, so let's quit
@rcvdInterrupt
move.b #0,OSSMsk60Hz(a0) ;disable 60Hz interrupt while moving vectors
move.l a2,(a1) ;restore os level 1 vector
subq #1,d6 ;go down one level
subq #4,a1 ;get next vector down
tst.b d6 ;are we at zero yet?
bne.s @nextLevel ;do next level
@OSSIntTestEnd
move.b d2,OSSMsk60Hz(a0) ;restore old value of 60Hz IMR
move.w d5,sr ;restore old status
RTS6 ;return to caller
;----------------------------------------------------------------------
; This handler simply acknowledges the 60Hz int.
;----------------------------------------------------------------------
myIntHandler
move.b #0,OSS60HzAck(a0) ;acknowledge 60Hz interrupt
move.l #OssIntSig,d0 ;load d0 with our signature
; so we know we've been here
rte
OSSIntAbort
moveq #-1,d6 ;load fail/no-log code
RTS6 ;return to caller
RPUTest
;-------------------------------------------------------------------------------
; Routine: #93: RPUTest
;
; Inputs: a0 - ptr to table of hardware base addresses
; d0 - bit mask indicating which base addresses are valid
; d2 - boxflag/decoder type
; a6 - return address
;
; Outputs: d6 - 0 if test passes, fail code otherwise
;
; Destroys: d0,d1,d4,d5,a3,a4,a6
;
; This routine will test the Ram Parity Unit on Zone-5, if present. Since these
; non-critical tests don't know where RAM is (i.e. chunk table), we just pick
; a location below the stack to test. If the Test Manager could be assured to
; know where the chunk table was, then this (and the above PGC test) could be
; modified to test a spot in all banks, thus testing the complete RPU or PGC chip.
;
; Note that this test assumes that the parity bit in d7 is set. This assumption <25>
; is only valid during startup diagnostics. If this test is run from the serial <25>
; test manager or the _TestManager trap, the parity bit in d7 is not guaranteed <25>
; to be set properly. (Of course, this is a destructive test so you shouldn't <25>
; run it from the _TestManager trap anyway). <25>
;
;-------------------------------------------------------------------------------
btst.l #DecoderInfo.RPUExists,d0 ;<25>
beq.s @exit
btst #parity,d7 ;is parity ram installed?
beq.s @exit ;no, don't run RPU test
movea.l DecoderInfo.RPUAddr(a0),a3 ;Get RPU base address (also needed by NMI) <21>
move.l a6,-(sp) ;save return address
movea.l a7,a5 ;mark sp for NMI handler
bset.l #beok,d7 ;tell the bus error handler it's ok
move.l #RPUParity,d0 ;tell the NMI that we expect parity errors
moveq #32-1,d5 ;loop counter
moveq #1,d4 ;test value
lea -4(sp),a4 ;grab a long off the stack
@step1
st.b rpuReset(a3) ;reset serial ptr
move.l (a3),d1
bset.l #24,d1 ;write wrong parity
move.l d1,(a3)
lea @step2,a6 ;NMI here means parity error (expected)
move.l d4,(a4) ;write test word with even parity
tst.l (a4) ;read (with odd parity), should get an error
bra.s @error ;no NMI, something's wrong
@step2
move.l (a3),d1
bclr.l #24,d1 ;write normal parity
move.l d1,(a3)
lea @step3,a6 ;NMI here means parity error (expected)
tst.l (a4) ;read, should get error here too
bra.s @error ;no NMI, something's wrong
@step3
lea @error,a6 ;NMI here means parity error
move.l d4,(a4) ;write test word with odd parity
tst.l (a4) ;read word, shouldn't have parity error
rol.l #1,d4 ;check next bit
dbra d5,@step1
moveq.l #0,d6 ;set successful completion code
bra.s @good ;parity ok, exit with it enabled
@error move.l #parityErr,d6 ;signal we got a parity error
move.l (a3),d1
bclr.l #24,d1 ;write normal parity
move.l d1,(a3)
@good
moveq.l #0,d0 ;clear the parity error signature
bclr.l #beok,d7 ;clear the bus error OK flag
rts ;return to caller
@exit moveq.l #-1,d6 ;load fail/no-log code
RTS6 ;return to caller
; The Egret test and the sound interrupt test (which follows) were added for version
; <8> of this file.
EgretTest
;-------------------------------------------------------------------------------
; Routine: #94: EgretTest
;
; Inputs: a0 - ptr to table of hardware base addresses
; a1 - ptr to product information table
; a6 - return address
;
; Outputs: d6 - 0 if test passes, fail code otherwise
;
; Destroys:
;
; This routine tests the Egret chip by executing the Egret "execute diagnostics"
; command.
;-------------------------------------------------------------------------------
move.l a6,-(sp) ;save return address
WITH ProductInfo
move.l ExtValid(a1),d0
andi.l #ClockMask,d0
cmpi.l #ClockEgret,d0
bne.w @exit ;No Egret - exit immediately
; now chk for Egret8/Caboose or Cuda FW <SM4> rb
move.l ExtValid(a1),d0 ; <SM4> rb
andi.l #EgretFWMask,d0 ; mask all but Egret FW bits <SM4> rb
cmpi.l #Cuda,d0 ; chk for Cuda FW <SM4> rb
beq.w CudaTest ; If Cuda, go do it!!! <SM4> rb
; else FW is Egret8 or Caboose, drop thru <SM4> rb
ENDWITH
movea.l DecoderInfo.VIA1Addr(a0),a2 ;point to VIA1 base <21>
moveq #1,d6 ;Step #1 - is Egret already busy?
btst.b #vXcvrSesbit,vBufB(a2) ;Is XCVR Session asserted? (active low)
beq.w @end ;exit if so
addq.l #1,d6 ;Step #2 - IRQ timeout on 1st byte <16>
ori.b #ACRmode,vacr(a2) ;Init the VIA mode <16>
bset.b #SRdir,vACR(a2) ;Set output mode <16>
bset.b #vSysSesbit,vBufB(a2) ;Assert Sys Session signal <16>
move.b #pseudopkt,vSR(a2) ;Put data in VIA data reg <16>
bset.b #vViaFullBit,vBufB(a2) ;Assert VIA Full <16>
move.w #$7FFF,d0 ;Set a large timeout value <16>
@PktTpWt btst.b #ifSR,vIFR(a2) ;Wait for IRQ <16>
dbne.w d0,@PktTpWt ;Count down our timeout cntr <16>
tst.b vSR(a2) ;Read Attn byte (clears IRQ) <16>
tst.w d0 ;See if we timed out <16>
bmi.w @Egretdone ;If we're hung up - error out <16>
addq.l #1,d6 ;Step #3 - Packet aborted by Egret <16>
bclr.b #vViaFullBit,vBufB(a2) ;De-assert VIA Full <16>
BSR6 TM_Wait ;Wait for Egret to see it <16><SM4> rb
btst.b #vXcvrSesbit,vBufB(a2) ;Is XCVR Session asserted? (active low) <16>
beq.w @Egretdone ;Error out if asserted <16>
addq.l #1,d6 ;Step #4 - IRQ timeout (detected below)
moveq #egretdiags,d2 ;Send the command byte
BSR6 TM_SendByte ; <SM4> rb
bclr.b #SRdir,vACR(a2) ;Define direction FROM Egret <13>
bclr.b #vSysSesbit,vBufB(a2) ;De-assert SYS SESSION
move.w #$ffff,d0
@WtForEgret btst.b #ifSR,vIFR(a2) ;Poll for IRQ
beq.s @NoIRQYet ;Continue until set <16>
btst.b #vXcvrSesbit,vBufB(a2) ;Is XCVR Session asserted? (active low)
beq.s @RcvPacket ;OK - go get response packet <16>
@NoIRQYet dbra d0,@WtForEgret ;Continue waiting for Egret <16>
bra.w @Egretdone ;Timed out - go report the error <16>
@RcvPacket move.b vSR(a2),d2 ;Read the response packet (clears IRQ) <16>
BSR6 TM_Wait ;Now, wait <16><SM4> rb
bset.b #vSysSesbit,vBufB(a2) ;Set Sys Session again
addq.l #1,d6 ;Next possible problem - xcvr session off too early
swap d6
move.w #4,d6 ;Set # bytes expected (minus 1)
link a6,#-6 ;Allocate some space on the stack
@read_data movem.l d6/a6,-(sp)
BSR6 TM_GetByte ;Read a byte - response packet type <SM4> rb
movem.l (sp)+,d6/a6
sne d0
move.b d2,-6(a6,d6.w) ;Put data on the stack
tst.b d0
bne.s @testend ;xcvr session turned off see if we're done
dbra.w d6,@read_data
swap d6
bra.s @readerr ;xcvr session still on - error out
@testend tst.w d6
beq.s @40 ;xcvr session was off early
swap d6
bra.s @readerr
@40 swap d6 ;Packet is now read
addq.l #1,d6 ;Next possible problem - wrong return packet
cmp.b #egretdiags,-4(a6) ;Is this the correct packet?
bne.w @readerr ;Get out of here if not
addq.l #1,d6 ;Next possible problem - Egret returned error
tst.b -3(a6) ;Egret reports error?
beq.s @Success ;Branch if not
cmp.b #3,-3(a6) ;does Egret report an ADB error?
bne.s @StillWrong ;continue if not
WITH ProductInfo
moveq.l #ADBMask,d0 ;else, get the ADB mask
and.l ExtValid(a1),d0 ;get the external features valid flags
cmp.w #ADBEgret,d0 ;do we have Egret ADB?
bne.s @Success ;Success if not
; (Egret cannot know about ADB failures)
ENDWITH ;else, ADB should work - report the error
@StillWrong
moveq.l #0,d6 ;set up d6 for error
move.b -3(a6),d6 ;diagnostic error response
rol.l #8,d6
move.b -5(a6),d6 ;diagnostic data #1
rol.l #8,d6
move.b -6(a6),d6 ;diagnostic data #2
bset.l #31,d6 ;this bit indicates Egret detected an error
bra.s @readerr
@success moveq #0,d6 ;Everything's OK
@readerr unlk a6
@Egretdone bclr.b #vViaFullBit,vBufB(a2) ;De-assert VIA Full
bclr.b #vSysSesbit,vBufB(a2) ;Turn off SYS Session
BSR6 TM_Wait ;Wait
bra.s @end ;then exit immediately
@exit
moveq #-1,d6
@end rts
; _______________________________________
; <SM4> rb, Cuda code
;
; _______________________________________
CudaTest
;
; Cuda Communications protocol is different from the Egret8 and Caboose, <P4> gjs
; so this code will handle the new protocol. |
; V
movea.l DecoderInfo.VIA1Addr(a0),a2 ;point to VIA1 base
moveq #1,d6 ;Step #1 - is Cuda already busy?
btst.b #TReq,vBufB(a2) ;Is TReq asserted? (active low)
beq.w @end ;exit if so
addq.l #1,d6 ;Step #2 - IRQ timeout on 1st byte
ori.b #ACRmode,vacr(a2) ;Init the VIA mode
bset.b #SRdir,vACR(a2) ;Set output mode
move.b #pseudopkt,vSR(a2) ;Put data in VIA data reg
bset.b #vByteAck,vBufB(a2)
bclr.b #TIP,vBufB(a2) ;Assert TIP signal
move.w #$7FFF,d0 ;Set a large timeout value
@PktTpWt btst.b #ifSR,vIFR(a2) ;Wait for IRQ
bne.s @GotIRQattn
dbne.w d0,@PktTpWt ;Count down our timeout cntr
@GotIRQattn tst.b vSR(a2) ;Read Attn byte (clears IRQ)
tst.w d0 ;See if we timed out
bmi.w @Cudadone ;If we're hung up - error out
addq.l #1,d6 ;Step #3 - Packet aborted by Cuda
btst.b #TReq,vBufB(a2) ;Is TReq asserted? (active low)
beq.w @Cudadone ;Error out if asserted
addq.l #1,d6 ;Step #4 - IRQ timeout (detected below)
moveq #EgretDiags,d2 ;Send the command byte
BigBSR6 CudaWriteByte,a4
bclr.b #SRdir,vACR(a2) ;Define direction FROM Cuda
bset.b #TIP,vBufB(a2) ;Negate TIP
move.w #$ffff,d0
@WtForCuda btst.b #ifSR,vIFR(a2) ;Poll for IRQ
beq.s @NoIRQYet ;Continue until set
btst.b #TReq,vBufB(a2) ;Is TReq asserted? (active low)
beq.s @RcvPacket ;OK - go get response packet
@NoIRQYet dbra d0,@WtForCuda ;Continue waiting for Cuda
bra.s @Cudadone ;Timed out - go report the error
@RcvPacket move.b vSR(a2),d2 ;Read the response packet (clears IRQ)
bclr.b #TIP,vBufB(a2) ;assert TIP to begin response packet
addq.l #1,d6 ;Next possible problem - TReq off too early
swap d6
move.w #4,d6 ;Set # bytes expected (minus 1)
link a6,#-6 ;Allocate some space on the stack
@read_data movem.l d6/a6,-(sp)
BigBSR6 CudaReadByte,a4 ;Read a byte - response packet type
movem.l (sp)+,d6/a6
sne d0
move.b d2,-6(a6,d6.w) ;Put data on the stack
tst.b d0
bne.s @testend ;TReq turned off see if we're done
dbra.w d6,@read_data
swap d6
bra.s @readerr ;TReq still on - error out
@testend tst.w d6
beq.s @40 ;TReq was off early
swap d6
bra.s @readerr
@40 swap d6 ;Packet is now read
addq.l #1,d6 ;Next possible problem - wrong return packet
cmp.b #EgretDiags,-4(a6) ;Is this the correct packet?
bne.w @readerr ;Get out of here if not
addq.l #1,d6 ;Next possible problem - Cuda returned error
tst.b -3(a6) ;Cuda reports error?
beq.s @success ;Branch if not
moveq #0,d6 ;set up d6 for error
move.b -3(a6),d6 ;diagnostic error response
rol.l #8,d6
move.b -5(a6),d6 ;diagnostic data #1
rol.l #8,d6
move.b -6(a6),d6 ;diagnostic data #2
bset.l #31,d6 ;this bit indicates Cuda detected an error
bra.s @readerr
@success moveq #0,d6 ;Everything's OK
@readerr unlk a6
@Cudadone ori.b #((1<<TIP)|\ ; terminate the transaction
(1<<vByteAck)),vBufB(a2)
move.w #$7FFF,d0 ;Set a large timeout value
@PktIdleWt btst.b #ifSR,vIFR(a2) ;Wait for Idle state IRQ
bne.s @GotIRQlast
dbne.w d0,@PktIdleWt ;Count down our timeout cntr
@GotIRQlast tst.b vSR(a2) ;Read Attn byte (clears IRQ)
tst.w d0 ;See if we timed out
bra.s @end ;then exit immediately
@exit
moveq #-1,d6 ; ^
@end ; |
rts ; <P4> gjs
;______________________________________________________
; <SM4> rb, end of Cuda code
;______________________________________________________
TestSndInts ;
;--------------------------------------------------------------------------------------------------------------
;
; #95: Sound Interrupts test <23>
; This test checks that Sound interrupts are functioning properly.
; Both Play and Record modes are checked.
; For the moment test is only executed on machines with a VIA2 or
; the RBV implementation of it
;
; Inputs: a0 - points to table of hardware base addresses
; d0 - bits indicating which base address are valid
; d2.lw - boxflag/decoder type
; d2.hw - private feature flags
;
; Outputs: d6.l - error code, -1 if test not applicable
; 00x00000 if test passed
; 00x00008 if Chan B Full Int did not occur (play mode)
; 00x00004 if Chan B Half Full Int did not occur (play mode)
; 00x00002 if Chan A Full Int did not occur (play mode)
; 00x00001 if Chan A Half Full Int did not occur (play mode)
; 00x08000 if half full interrupt did not occur (record mode) <SM6>
; 00x08001 if Chan A Full Int did not occur (record mode)
; 00x08002 if Chan A Full flag did not go active (record mode)
;
; Where x is the upper nibble of the sound version register, which has
; the following meaning:
; 0 - Original ASC chip
; E - Elsie style VISA implementation of sound
; B - Batman sound
;
; Note: If bit 31 is set in one of these error codes, then the test believes
; that it is running on an Elsie.
; Called by BSR6
;--------------------------------------------------------------------------------------------------------------
WITH DecoderInfo ;<21>
btst.l #ASCExists,d0 ;have an ASC?
beq noSndInt ;no, exit
movem.l d0-d1/d3-d5/d7/a0-a4,-(sp) ;ok to use a stack here:
move.w sr,-(sp) ;called by non-crit (after stk ram tested)
ori.w #hiIntMask,sr ;turn ints off
moveq.l #0,d4 ;clear the actual int status reg <17>
movea.l #0,a3
btst.l #VIA2Exists,d0 ; see if we have VIA2
beq.s @VIA2done ; if not, skip it
movea.l VIA2Addr(a0),a3 ; get VIA2 base address
move.l #$1A001C00,d7 ;get the IFR/IER offsets in hw/lw of d7
@VIA2done
btst.l #RBVExists,d0 ; see if we have an RBV
beq.s @RBVdone ; if not, skip it
movea.l RBVAddr(a0),a3 ; get RBV base address
move.l #$00030013,d7 ;get the IFR/IER offsets in hw/lw of d7
@RBVdone
moveq.l #-1,d6 ;prepare for an error
cmpa.l #0,a3 ; Have we a valid base address
beq @noBaseFound ; no, don't run test
moveq.l #0,d6 ; clear error register <17>
movea.l a3,a5 ;get a VIA address for delays <T9>
btst.l #VIA1Exists,d0 ;do we have a VIA1? <T9>
beq.s @noVIA1 ;branch if not <T9>
movea.l VIA1Addr(a0),a5 ;else, get the VIA1 address <T9>
@noVIA1 ; <T9>
ENDWITH ;<21><T9>
movec.l vbr,a4 ;Get the vector base register <17>
move.l AutoVector2(a4),-(sp) ; save current interrupt vector <17>
move.b (a3,d7.w),-(sp) ; save currently enabled interrupts <H22><SM6>
ori.b #$80,(sp) ; make sure to set high bit for later <H22><SM6>
move.b #$7f,(a3,d7.w) ; disable all via2 interrupts <H22><SM6>
swap d7 ; d7 points to IFR <H22><SM6>
move.b #$10,(a3,d7.w) ; clear pending via2 sound interrupts <H23><SM6>
lea IntHdlr,a1 ; and load the new one
move.l a1,AutoVector2(a4) ; <17>
movea.l DecoderInfo.ASCAddr(a0),a4 ;point to ASC base <21><18>
move.b ascVersion(a4),d3 ;Get the ASC version number <18>
cmp.b #batmanSound,d3 ; check for original Batman <H21><SM6>
beq.s @OriginalBatman ; we've got one, so work with both channels <H21><SM6>
move.b d3,d6 ;Put the sound type in return status reg <18>
swap d6 ; <18>
and.b #$f0,d3 ;mask off the batman bits <18><SM6>
cmp.b #batmanSound,d3 ;is this a batman? <18>
bne @notBatman ;branch if not <18>
move.w #$0E,d5 ; this is the "play" half empty/full flag combo for <H21><SM6>
; channel B and the record full/empty flag (Batman <H21><SM6>
; derivatives only, such as Sonora and djMEMC) <H21><SM6>
bra.s @begin ; start the first test <H21><SM6>
@OriginalBatman ; <H21><SM6>
move.b d3,d6 ; put the sound type in the return status <H21><SM6>
swap d6 ; <H21><SM6>
move.w #$0F,d5 ; this is the FIFO interrupt mask for original Batman <H21><SM6>
@begin
move.w #$FFFF,d6 ;Set timeout value for FIFO emptying <18>
bset.l #30,d6 ;indicate what we're doing <18>
@Wait4FIFO tst.b (a5) ;delay a little <T9>
cmp.b ascFIFOInt(a4),d5 ;are the FIFO(s) empty? <H21>
dbeq.w d6,@Wait4FIFO ;Continue waiting until they have or timeout<18>
bne.w @errexit ;Exit if FIFOs did not clear <18>
bclr.l #30,d6 ;That test passed... <18>
clr.w d6 ;clear out the timeout status <18>
move.b #1,bmIntControlA(a4) ;Disable ints on channel A <18>
move.b #1,bmIntControlB(a4) ;Disable ints on channel B <18>
clr.b bmFifoControlA(a4) ;turn off the SRC flag in channel A <18>
clr.b bmFifoControlB(a4) ;and in channel B <18>
move.b #$3F,bmSrcTimeIncrA(a4) ;Set for 11Khz <18>
move.b #$DB,bmSrcTimeIncrA+1(a4) ;for channel A <18>
move.b #$3F,bmSrcTimeIncrB(a4) ;Set for 11Khz <18>
move.b #$DB,bmSrcTimeIncrB+1(a4) ;for channel B <18>
bset.b #7,bmFifoControlA(a4) ;turn on the SRC flag in channel A <18>
bset.b #7,bmFifoControlB(a4) ;and in channel B <18>
clr.b ascPlayRecA(a4) ;Set channel A to play mode <18>
clr.b ascPlayRecB(a4) ;and set channel B to play mode <18>
bset.b #7,ascFifoControl(a4) ;reset the FIFO ptrs <18>
bclr.b #7,ascFifoControl(a4) ;(pulse the FIFO strobe) <18>
clr.b ascChipControl(a4) ;Clear out any pending overflow status <18>
move.b #$01,ascMode(a4) ;Start the chip running <18>
bra.s @enableASCInts ;and continue <18>
@notBatman
move.b #$1,ascMode(a4) ;set mode to FIFO
move.b #$0,ascPlayRecA(a4) ;ensure play mode <17>
move.b #$80,ascFifoControl(a4) ;reset the FIFO ptrs <17>
move.b #0,ascFifoControl(a4) ; <17>
tst.b ascFifoInt(a4) ;clear pending interrupt flags <17>
move.b #2,ascChipControl(a4) ;stereo mode <17>
move.b #0,ascWaveOneShot(a4) ;clear one shot modes/flags <17>
move.b #0,ascVolControl(a4) ;volume = 0 <17>
move.b #0,ascClockRate(a4) ;clk mode = 22.257Khz (Mac) <17>
@enableASCInts
swap d7 ;make d7 point to IER <H23><SM6>
move.b #$90,(a3,d7.w) ;enable sound interrupts <17>
move.b #$6f,(a3,d7.w) ;disable all other interrupts <17>
swap d7 ;make d7 point to IFR for interrupt handler <H23><SM6>
move.b #$10,(a3,d7.w) ;clear sound interrupt, if pending <H23><SM6>
cmp.b #elsieSound,d3 ;is this an Elsie style asc? <18>
bne.s @ChanB ;branch to test channel B if not <18>
@ElsieSound
bset.l #31,d6 ;Else, indicate we're on an Elsie <17>
bra.w @ChanA ;and test channel A only <17><H21><SM6>
@ChanB lea ascFifoRight(a4),a2 ;Point to channel B FIFO <17>
@TestPlay move.b #$8,d6 ;initialize expected interrupt Chan B <SM6>
cmp.b #batmanSound,d3 ;are we on a batman? <18>
bne.s @ChBnotbat ;continue if not <18>
clr.b bmIntControlB(a4) ;Else enable ints on channel B <18>
move.b #$10,(a3,d7.w) ;clear sound interrupt, if pending <H23><SM6>
move.w #1000,d5 ;put some stuff into the FIFO <18>
@FillB move.b d0,(a2) ;so that we don't interrupt immediately <18>
dbra.w d5,@FillB ; <18>
@ChBnotbat
bsr FIFOFill ;Fill the FIFO until we get a FIFO full int <18>
bpl.s @ChBFIFOFull ;jump if we did not get the interrupt <18>
cmp.b #batmanSound,d3 ;are we on a batman? <18>
bne.w @errexit ;we have an error if not <18>
@ChBFIFOFull
lsr.b #1,d6 ; set expected interrupt
bsr WaitforInt
bmi.w @errexit ; jump if we did not get the interrupt
cmp.b #batmanSound,d3 ;are we on a batman? <18>
bne.s @ChanA ;continue if not <18>
lsl.b #1,d6 ;Else look for the FIFO empty status <18>
move.w #$7FFF,d1 ;Set a timeout <18>
@WtFIFOFull tst.b (a5) ;wait a little <T9>
move.b ascFifoInt(a4),d5 ;Get the FIFO status <18><T9>
and.b d6,d5 ;Is the FIFO empty? <18>
dbne.w d1,@WtFIFOFull ;Terminate when so <18>
beq.w @errexit ;error out if we don't get it <18>
; At this point we must determine if we're running a BatRat (derivative of a <H21><SM6>
; Batman sound implementation). For example, on Sonora, channel A is for record <H21><SM6>
; only, so we can't test play. We will jump down to the record tests if we're <H21><SM6>
; on a BatRat. D3 currently contains a masked sound version, so we need to <H21><SM6>
; get the "real" sound version and check it: <H21><SM6>
move.b ascVersion(a4),d3 ; get the ASC version number <H21><SM6>
cmp.b #batmanSound,d3 ; see if this is a "real" Batman ($B0) <H21><SM6>
beq.s @realBatmanContinue ; continue if so <H21><SM6>
cmp.b #wombatSound,d3 ; see if this is a Wombat batrat <H24><SM6>
beq.b @WombatContinue ; go test channel B play for Wombat <H24><SM6>
and.b #$f0,d3 ; mask it to see if it's a BatRat <H21><SM6>
cmp.b #batmanSound,d3 ; and check <H21><SM6>
beq.w @TestRecord ; branch down and test recording if so <H21><SM6>
bra.s @realBatmanContinue ; default behavior from before
@WombatContinue ; <H24><SM6>
and.b #$f0,d3 ; mask it for BatRat <H24><SM6>
move.l a2,d5 ; save for compare <H24><SM6>
lea ascFifoLeft(a4),a2 ; get the address of channel A <H24><SM6>
cmp.l a2,d5 ; see if we've already done this <H24><SM6>
beq.w @TestRecord ; continue with the record test <H24><SM6>
lea ascFifoLeft(a4),a2 ;Point to channel B FIFO <H24><SM6>
bra.w @TestPlay ; <H24><SM6>
@realBatmanContinue ; <H21><SM6>
ori.w #hiIntMask,sr ;turn ints off <18>
move.b #1,bmIntControlB(a4);Then disable ints on channel B <18>
clr.b bmIntControlA(a4) ;and enable ints on channel A <18>
move.b #$10,(a3,d7.w) ;Clear any pending sound interrupt <H23><SM6>
clr.l d4 ;and clear our local int register <18>
@ChanA lea ascFifoLeft(a4),a2 ; point to channel A FIFO <17>
move.b #$2,d6 ; initialise expected interrupt for Chan A
move.w #1000,d5 ;put some stuff into the FIFO <17>
@FillA move.b d0,(a2) ;so that we don't interrupt immediately <17>
dbra.w d5,@FillA ;on Elsie <17>
bsr FIFOFill ;Fill the FIFO <17>
bpl.s @ChAFIFOFull ;jump if we got the interrupt <17>
btst.l #31,d6 ;Else, are we on an Elsie? <17>
bne.s @ChAFIFOFull ;Branch if so (We don't expect this int) <18>
cmp.b #batmanSound,d3 ;Else are we on a batman? <18>
bne.w @errexit ;we have an error if not <18>
@ChAFIFOFull
lsr.b #1,d6 ;set expected interrupt
bsr WaitforInt
bmi.w @errexit ;jump if we did not get the 1/2 full int <18>
btst.l #31,d6 ;Are we on an Elsie? <18>
bne.s @ChAEmpty ;if so, look for FIFO empty int <18>
cmp.b #batmanSound,d3 ;Else, is this a batman? <18>
bne.s @Continue ;Continue if not <18>
@ChAEmpty lsl.b #1,d6 ;Else look for the FIFO empty int <17>
bsr WaitforInt ; <17>
bpl.s @Continue ;Keep going if we got it <18>
cmp.b #batmanSound,d3 ;Else, is this a batman? <18>
bne.w @ErrExit ;error out if not <18><H22>(changed from beq.s to beq.w)<SM6>
move.b ascFifoInt(a4),d5 ;else get the fifo status <18>
and.b d6,d5 ;See if the FIFO is empty <18>
beq.w @ErrExit ;Error out if not <18><H22>(changed from beq.s to beq.w)<SM6>
@Continue ; <17>
bset.b #7,ascFifoControl(a4) ; reset the FIFO ptrs <17>
bclr.b #7,ascFifoControl(a4) ; <17>
cmp.b #elsieSound,d3 ;is this an Elsie style asc? <18>
beq.s @TestRecord ;If yes, test Record interrupts <18>
cmp.b #batmanSound,d3 ;Else is this a batman? <18>
beq.s @TestRecord ;if yes, test record also <18>
move.w d2,d1 ; get boxflag
lsr.w #8,d1 ;
cmpi.b #BoxMacIIsi,d1 ; -or- is it a IIsi (Erickson?) <29>
bne.s @NoRecord ; no, don't test Record interrupts
@TestRecord ori.w #hiIntMask,sr ;turn ints off <18>
clr.w d6 ;Clear the low word of status reg <17>
move.b #1,bmIntControlB(a4);Then disable ints on channel B <18><H23><SM6>
swap d7 ; make d7 point to IER <H22><SM6>
move.b #$10,(a3,d7.w) ; disable sound interrupts at via2 <H22><SM6>
swap d7 ; make d7 point to IFR for Interrupt handler<H22><SM6>
bset.b #7,ascFifoControl(a4) ; reset the FIFO ptr <17><H22><SM6>
bclr.b #7,ascFifoControl(a4) ; <17><H22><SM6>
move.b #$10,(a3,d7.w) ;Clear pending sound ints at via2 <18><H23><SM6>
bset.l #15,d6 ; and indicate record mode <17><H22><SM6>
cmp.b #batmanSound,d3 ;Are we on a batman? <18>
bne.s @notBatmanRecord ;branch if not <18>
move.b #1,bmIntControlA(a4) ;Disable interrupts <18>
clr.b bmIntControlA(a4) ;and re-enable them <18>
@notBatmanRecord
tst.b ascFifoInt(a4) ; clear pending interrupt flags <17>
swap d7 ; make d7 point to IER <H22><SM6>
move.b #$90,(a3,d7.w) ; enable sound interrupts <H22><SM6>
swap d7 ; d7 points to IFR for interrupt handler <H23><SM6>
move.b #$3,ascPlayRecA(a4) ; set record mode, 22KHz Sample rate <17><H22><SM6>
move.w #$7fff,d5 ; initialise timeout counter <17>
move.w #$2100,sr ; enable ints <17>
@RecIntWt tst.b (a5) ; delay a bit <17><T9>
tst.w d6 ; any errors <17>
dbeq.w d5,@RecIntWt ; wait for FIFO to fill <17>
bne.s @errexit ; jump if we didn't get full <T9>
@NoRecord clr.l d6 ; all is well
@errexit ori.w #hiIntMask,sr ;turn ints off <17>
swap d7 ; point d7 to the IER <H23><SM6>
move.b #$10,(a3,d7.w) ; disable sound interrupts <17>
swap d7 ;d7 points to IFR <H23><SM6>
move.b #$80,ascFifoControl(a4) ; reset the FIFO ptrs <17>
move.b #0,ascFifoControl(a4) ; <17>
move.b #$0,ascPlayRecA(a4) ; set play mode <17>
movec.l vbr,a0 ;Get the vector base register <17>
swap d7 ; d7 points to IER <H23><SM6>
move.b (sp)+,(a3,d7.w) ; restore enabled interrupts for via2 <H22><SM6>
move.l (sp)+,AutoVector2(a0) ;restore interrupt vector <17>
@noBaseFound
move.w (sp)+,sr ; restore interrupt level
movem.l (sp)+,d0-d1/d3-d5/d7/a0-a4 ; restore registers
RTS6 ; return to caller
IntHdlr move.b (a3,d7.w),d0 ; read interrupt flags <17><T9>
btst #4,d0 ; was it a Sound interrupt
bne.s @validInt ; yes, jump
move.b #$ff,d6 ; flag error <18>
move.w sr,(sp) ;disable ints in saved status register <17>
bra.s @Error
@validInt move.b ascFifoInt(a4),d4 ; get FIFO interrupt status <17>
btst.l #15,d6 ; play or record int expected <18>
bne.s @RecordInt ; go handle record case
andi.b #$f,d4
btst.l #31,d6 ;Are we on an Elsie? <18>
beq.s @PlayExit ;Continue if not <17>
move.w sr,(sp) ;else, make sure we don't interrupt again <17>
bra.s @PlayExit ;Then exit. <17>
@RecordInt cmp.b #batmanSound,ascVersion(a4) ;Is this a batman? <18><H22><SM6>
beq.s @batRecInt ;branch if so <18>
btst.l #0,d4 ;Else, this bit should be set (half full int)<18>
bne.s @recOK ;Continue if all OK <18>
bra.s @HFError ;Else error out <18>
@batRecInt btst.l #0,d4 ;Batman record int - this bit should be 0 <18>
bne.s @HFError ;Error out if it isn't <18>
@recOK move.w #$7fff,d1 ; initialise timeout counter
@wait tst.b (a5) ; delay a bit <18><T9>
btst.b #1,ascFifoInt(a4) ;Is the record FIFO full? <18>
dbne.w d1,@wait ;Continue until we get the full flag <18>
bne.s @RecordExit ;Clean done if we got our int <18>
move.b #$02,d6 ;No full status in record mode <18>
bra.s @Error
@HFError move.b #$01,d6 ; flag error
bra.s @Error
@RecordExit clr.w d6 ; clear error reg
@Error swap d7
move.b #$10,(a3,d7.w) ; disable sound interrupts <17>
swap d7
@PlayExit move.b #$90,(a3,d7.w) ; clear sound interrupt flag <17>
rte
FIFOFill move.w #2000,d5 ; 1k < loop count < 2k bytes <17>
@FillLoop move.w #$2100,sr ;enable ints <17>
move.b d0,(a2) ;Send a byte to the FIFO <17>
and.b d6,d4 ;have we gotten a full interrupt yet? <18>
dbne.w d5,@FillLoop ;keep filling if not <17>
tst.w d5 ;Return with status saying if we got the int<17>
rts
WaitforInt move.w #$7fff,d1 ;initialise timeout counter <18>
@WaitLoop move.w #$2100,sr ;enable ints <17>
tst.b (a5) ;delay a bit <17><T9>
and.b d6,d4 ;see if we got our int <18>
dbne.w d1,@WaitLoop ;keep going until we do, or until we T/O <17>
tst.w d1 ;return with status of timeout counter <17>
rts
noSndint moveq #-1,d6 ;load fail/no-log code
RTS6 ;return to caller
;From here to the next <21> below was added for the new CLUT test
TestCLUT
;-----------------------------------------------------------------------------
;
; #96: CLUT RAM test <23>
; This tests the 3 by 256 by 8 Color Lookup Table (CLUT) which is found in
; the brooktree and Ariel color palette chips. The test writes the values
; 0 through 255 into the RGB CLUT regs, then reads back and verifies.
;
; Inputs: a0 - decoder info record
; a1 - product info record
;
; Ouputs: d6 - result
;
; Destroys: d0 <23>
;
;-----------------------------------------------------------------------------
WITH ProductInfo, DecoderInfo
move.l BasesValid(a1),d0 ;Get the valid bases flags
btst.l #VDACExists,d0 ;Do we have a VDAC?
beq.w @noRBV ;Test does not apply
moveq.l #0,d6 ;zero out the result register <23>
move.l a6,-(sp) ;save return address so we can use rts later<23>
movem.l a0/a2-a4/d1-d3,-(sp) ;save some registers <28><23><H20><SM6>
movea.l a0,a4 ;save this for later <H20><SM6>
movea.l VDACAddr(a0),a0 ;Get the VDAC address <23>
ENDWITH ;ProductInfo, DecoderInfo
move.b vDACPixRdMask(a0),-(sp) ;Save the pixel mask <23>
move.b #$FF,vDACPixRdMask(a0) ;set the vDAC mask
movea.l a0,a2 ;save a2 for loading <28>
; Identify the particular VDAC we have and setup some registers as appropriate: <H20><SM6>begin
move.b ProductInfo.ProductKind(a1),d0 ;Get the box flag <28>
cmp.b #BoxMacLC,d0 ;Is this an Elsie with V8? <28>
beq.s @itsLC ; yes its an LC <SM8>
cmp.b #BoxMacLCII,d0 ; is this an LC II with V8? <SM8>
bne.s @checkSonora ; continue if not <H20>
@itsLC lea V8DACwDataReg(a2),a3 ; a3 is the data register address <H20><SM8>
lea V8DACwAddReg(a2),a0 ; a0 is the address register address <H20>
bra.s @startClutTest ; branch down and start testing <H20>
; OK, here's a snag. The Sonora has a certain issue with the dot clock (Omega)
; that requires US to make sure the dot clock is running in order to talk
; to Ariel. The potential problem is that if we are here and the dot clock
; hasn't been started by the video driver, then we need to start it ourselves.
; However, if it's already running, then we'd better leave it alone or we
; could screw up video (if we're running from XXTest, for example). So, we
; will look at the Video Mode register and look for $9F, which indicates that
; no clock is running. If so, we'll just stuff in a 13" RGB setting and run
; the test, then shut the clock off. In order to control Omega, we need to
; use Egret:
@checkSonora ; from this <H20> to the one below
WITH ProductInfo, DecoderInfo ;
moveq.l #0,d4 ; clear my "started Omega" flag just in case <H21>
move.l ExtValid(a1),d1 ; get the external valid flags
btst.l #SonoraExistsBit,d1 ; check for Sonora
beq.s @genericVDAC ; don't have one, so use "generic" offsets
lea ArielDataReg(a2),a3 ; a3 is the data register address
lea ArielAddrReg(a2),a0 ; a0 is the address register address
move.l VIA1Addr(a4),a2 ; get the Sonora base address
adda.l #SonoraVdCtlBase,a2 ; point to the video control address space
move.b SonoraVdModeReg(a2),d0 ; get the current video mode setup
cmp.b #$9F,d0 ; see if the dot clock is running
bne.s @startClutTest ; yes, so start the test
movem.l a0-a6/d1-d5,-(sp) ; save a bunch of stuff across SendEgretCmd
move.l a4,a0 ; prep this for the call
move.l #(WrDFAC<<16)+PseudoPkt,d0; the command packet & type
move.l #$5a72,d1 ; this is the command data (program Omega)
ori.l #(sndSonoraReverseDFAC<<24),d1 ; make sure the sound part of DFAC is correct
move.l #4,d2 ; four bytes to send
BigBSR6 SendEgretCmd,a1 ; program that Omega
movem.l (sp)+,a0-a6/d1-d5 ; restore these
tst.w d0 ; non-zero means there was an error
bne.w @egretError ; there was a problem, so bail out
moveq.l #1,d4 ; set a flag so I know to stop the dot clock later
bra.s @startClutTest ; branch down and start testing
ENDWITH ; <H20>
@genericVDAC ;
lea vDACwDataReg(a2),a3 ;a3 is the data register address <28>
lea vDACwAddReg(a2),a0 ;a0 is the address register address <28>
@startClutTest ; <H20><SM6>end
move.b #$00,(a0) ;Start at address 0
bsr @ClearRGBRegs ;Prepare the RGB regs
link a2,#-256*3 ;Allocate some space on the stack
movea.l sp,a2 ;Point a2 to the beginning <23>
move.w #$100-1,d0 ;Save all 256 locations (by 3)
@SaveClut
moveq.l #3-1,d2 ;Save in multiples of 3
@SaveRGB
move.b (a3),(a2)+ ;Save a byte <28><23>
dbra.w d2,@SaveRGB ;Get RGB
dbra.w d0,@SaveClut ;Continue until done
move.b #$00,(a0) ;Start filling at address 0
move.w #$100-1,d0 ;Prepare to fill the entire CLUT
move.b #-1,d1 ;Starting pattern is this plus 1
@FillClut
moveq.l #3-1,d2 ;Fill in increments of 3
@FillRGB
addq.b #1,d1 ;increment data
move.b d1,(a3) ;move data into data Red/Green/Blue <28>
dbra.w d2,@FillRGB ;continue filling with data
dbra.w d0,@FillClut ;continue filling with data
move.b #0,(a0) ;Back to address 0
bsr @ClearRGBRegs ;Prepare the RGB regs
move.w #$100-1,d0 ;verify 256 3 byte locations
move.b #-1,d1 ;value to compare
@VerifyClut
moveq.l #3-1,d2 ;Verify in increments of 3 also
@VerifyRGB
addq.b #1,d1 ;Increment verify data
move.b (a3),d3 ;read the CLUT <28>
cmp.b d3,d1 ;is this OK?
dbne.w d2,@VerifyRGB ;continue if so
dbne.w d0,@VerifyClut ;keep continuing if we're OK
beq.s @Done ;otherwise, we're done if OK
;Else, error:
neg.b d0 ;Derive the actual CLUT address <22>
subq.b #1,d0 ; <22>
neg.b d2 ;Derive RGB code (1=Red, 2=Green, 3=Blue) <22>
addq.b #3,d2 ; <22>
move.b d2,d6 ;Report R, G or B <22>
lsl.l #8,d6 ; <22>
move.b d0,d6 ;report address <22>
lsl.l #8,d6 ; <22>
move.b d1,d6 ;report expected
lsl.l #8,d6
move.b d3,d6 ;report actual
@Done
move.b #$00,(a0) ;Now to restore the Clut (start at addr 0)
move.w #$100-1,d0 ;Restore all 256 RGB locations
movea.l sp,a2 ;get the location to restore from <23>
@RestoreClut
moveq.l #3-1,d2 ;Restore in multiples of 3
@RestoreRGB
move.b (a2)+,(a3) ;Restore RGB <28>
dbra.w d2,@RestoreRGB ;Inner loop
dbra.w d0,@RestoreClut ;outer loop
unlk a2 ;Clean up the stack/restore a2
; If we're on a Sonora decoder (Vail), then we need to stop the dot clock <H20><SM6> to the one below
; if our "stop the dot clock" flag is set, indicating that we started it
; in order to run this test:
WITH ProductInfo, DecoderInfo ;
move.l ExtValid(a1),d0 ; get the external valid flags
btst.l #SonoraExistsBit,d0 ; check for Sonora (same VDAC as LC)
beq.s @skipSonoraRestore ; don't have one, so use skip this
tst.l d4 ; is my "stop dot clock" flag set?
beq.s @skipSonoraRestore ; no, so no need to stop it
move.l VIA1Addr(a4),a2 ; get the Sonora base address
adda.l #SonoraVdCtlBase,a2 ; point to the video control address space
movem.l a0-a6/d1-d5,-(sp) ; save a bunch of stuff across SendEgretCmd
move.l a4,a0 ; prep this for the call
move.l #(WrDFAC<<16)+PseudoPkt,d0; the command packet & type
move.l #$fffc,d1 ; this is the command data (program Omega)
ori.l #(sndSonoraReverseDFAC<<24),d1 ; make sure the sound part of DFAC is correct
move.l #4,d2 ; four bytes to send
BigBSR6 SendEgretCmd,a1 ; program that Omega
movem.l (sp)+,a0-a6/d1-d5 ; restore these
tst.w d0 ; look for an egret error
beq.s @skipSonoraRestore ; no problem, so continue
ENDWITH ;
@egretError ; before logging an Egret error, look for an
tst.l d6 ; error from the test itself; if there is one,
bne.s @skipSonoraRestore ; then DON'T wipe it out with the Egret error
move.w d0,d6 ; otherwise, return the message that
; there was a problem talking to Egret <H20>
@skipSonoraRestore ;
move.b (sp)+,vDACPixRdMask(a0) ;Restore the pixel mask
movem.l (sp)+,a0/a2-a4/d1-d3 ;restore the registers <23><28><H20><SM6>
rts ;and return
;
; This is a little utility routine that clears out the RGB latch registers.
; I call it after loading the CLUT address but before reading the CLUT data.
;
@ClearRGBRegs
move.b ProductInfo.ProductKind(a1),d0 ;Get the box flag <28><SM6>
cmp.b #BoxMacLC,d0 ;Is this an Elsie with V8? <28><SM6>
beq.s @return ;no action necessary if not <28><SM6>
cmp.b #BoxMacLCII,d0 ;is this an LC II with V8? <SM8>
beq.s @return ;no action necessary if not <SM8>
WITH ProductInfo ; <H20><SM6>
move.l ExtValid(a1),d0 ; get the external valid flags <H20><SM6>
btst.l #SonoraExistsBit,d0 ; check for Sonora (same VDAC on Vail as LC) <H20><SM6>
bne.s @return ; no action necessary if so <H20><SM6>
ENDWITH ; <H20><SM6>
@clearRegs ; <H20><SM6>
tst.b (a3) ;Read out the red <28>
tst.b (a3) ; green <28>
tst.b (a3) ; and blue holding regs <28>
@return
rts ;and return.
@noRBV
moveq.l #-1,d6 ;Test does not apply. Indicate with a -1
RTS6 ;and return
;From here to the next <21> above was added for the new CLUT test
;From here to next <T8> below is new. See comment below for details.
;-------------------------------------------------------------------------------------
;
; This routine determines VRAM size for machines equipped with seperate, dedicated
; video memory. These machines are:
;
; MacLC, Eclipse, TIM, Spike
; NOTE: to work on an LC, the routine SizeV8VRAM must have been called first!
;
; This routine returns the size of VRAM in D0 and a completion code in D6. The meaning
; of the completion code is as follows:
;
; d6 = 0 - success; d0 contains the VRAM size, even if zero!
; -1 - Test does not apply, machine does not support VRAM
; <09>0, <20>-1 - failure; d0 contains the VRAM size, however, d6 contains
; a bad byte lane bit mask. Bit 0 of each nibble, if set, indicates
; that byte lane zero is bad, bit 1 -> byte lane 1, etc.
;
; the low order nibble corresponds to the highest addressed bank
; of VRAM. Higher nibbles correspond to lower addressed up to the
; number of banks found as indicated in d0.
;
; This routine is called via BSR
;
; input:
; a0 - pointer to decoder info table
; a1 - pointer to product info table
;
; output:
; a0 - start address of VRAM
; a1 - end address of VRAM plus 1
; d0 - contains the size of VRAM
; d6 - see above
;
; destroyed:
; a2-a5, d0-d6
;
; Written by: Scott Smyers - 12/12/90
;
;-------------------------------------------------------------------------------------
DAFB_VRAM_Base EQU $F9000000
DAFB_BankSize EQU $80000 ;DAFB VRAM granulator: 512K bytes
dafb33MhzConfig Equ $00000F00 ;
dafbReleaseSwatch Equ 3 ;
dafbReassertSwatch Equ 7 ;
dafbReleaseVRamSM Equ 2 ;
dafbReleaseVideoSM Equ 0 ;
k256KvRAM EQU (256*1024) ; constant for 256Kb <H11><SM6>
Sonora256K Equ 0 ; Bank0=256K,Bank1=0 <H11><SM6>
Sonora512Ka Equ 1 ; Bank0=256K,Bank1=256K <H11><SM6>
Sonora512Kb Equ 4 ; Bank0=512K,Bank1=0 <H11><SM6>
Sonora768Ka Equ 2 ; Bank0=256K,Bank1=512K <H11><SM6>
Sonora768Kb Equ 5 ; Bank0=512K,Bank1=256K <H11><SM6>
Sonora1024K Equ 6 ; Bank0=512K,Bank1=512K <H11><SM6>
SonoraWrap Equ 512 ; <H11><SM6>
EXPORT SizeVRAM
SizeVRAM
WITH ProductInfo, DecoderInfo, DecoderKinds
MOVE.B DecoderKind(A1),D0 ; get the decoder type <H4>
CMPI.B #VISADecoder,D0 ; do we have a V8? <H4>
BNE.S @NotV8Video ; -> no <H4>
movea.l RBVAddr(a0),a2 ;get the RBV address
moveq.l #0,d0 ;now zero d0
btst.b #V8vRAMIn,V8Exp(a2) ;is there any VRAM?
beq @V8Done ;nope, leave d0 set to zero
move.l #1<<18,d0 ;else, report 256K of VRAM
btst.b #V8512Row,V8Exp(a2) ;do we have 512K?
bne.s @gotit ;we have the size if not
ADD.L D0,D0 ;else, adjust d0 to 512K
@gotit move.l VideoInfoPtr(a1),d1 ;get the video info pointer
movea.l (a1,d1.l),a0 ;then get the base address of video
lea (a0,d0.l),a1 ;and get the upper address value
@V8Done MOVEQ #0,D6 ; <H4>
RTS ; <H4>
@NotV8Video
CMPI.B #JAWSDecoder,D0 ; do we have JAWS (Tim)? <H4>
BNE.S @NotJawsVideo ; -> no <H4>
move.l #$8000,d0 ; get the size of the VRAM
move.l VideoInfoPtr(a1),d1 ; get pointer to video info table
movea.l (a1,d1.l),a0 ; get pointer to VRAM
lea (a0,d0.l),a1 ; point to end also
MOVEQ #0,D6 ; <H4>
RTS ; <H4>
@NotJawsVideo ; <H4>
; From here to the <H11> below was added to support sizing Sonora VRAM: <SM6>begin
cmpi.b #SonoraDecoder,D0 ; do we have Sonora (Vail)?
bne.l @NotSonoraVideo ; -> no
move.l VIA1Addr(a0),a3 ; use the DecoderInfo ptr to get to the via1 base
adda.l #SonoraVIA2Base,a3 ; from there, get the VIA2 base for later use
move.l VideoInfoPtr(a1),d1 ; get pointer to video info table
movea.l (a1,d1.l),a0 ; get pointer to VRAM (this will be the base of the Mod3 test)
move.l a1,a2 ; copy the ProductInfo pointer
adda.l ProductInfo.VideoInfoPtr(a1),a2 ; point to the VideoInfo record
move.l VideoInfo.VRAMLogAddr32(a2),a2 ; get the framebuffer base address
move.b #Sonora1024K,SonoraVRAMSize(a3) ; set up the hardware for 1Meg of VRAM
move.l #256*1024,d0 ; set our resulting size for 256k for now
move.l #'256K',(a2) ; write a signature to longword 0 in physbank 0
sub.l #4,(Sp) ; clear the data lines
add.l #4,(Sp)
cmp.l #'256K',SonoraWrap(a2) ; if we got our signature back, then
adda.l #k256KvRAM*2,a2 ; point to longword 0 in physbank 2
beq.s @256K ; it wrapped, so go on (256K on board)
add.l d0,d0 ; otherwise, we<77>ve got 512K on-board
bra.s @512Kb
@256K move.l #'512?',(a2) ; write signature to longword 0 in physbank 2
sub.l #4,(Sp) ; clear the data lines
add.l #4,(Sp)
cmp.l #'512?',(a2) ; if we got our signature back, then
beq.s @512Ka ; we<77>ve got expansion vRAM
move.b #Sonora256K,SonoraVRAMSize(a3) ; otherwise, there<72>s only 256K out there
bra.s @EndSize
@512Ka add.l d0,d0 ; say there<72>s at least 512K out there
cmp.l #'512?',SonoraWrap(a2) ; if we got our signature back, then
beq.s @Set512Ka ; it wrapped, so set 512K
move.b #Sonora768Ka,SonoraVRAMSize(a3) ; otherwise, there<72>s 768K out there
add.l #256*1024,d0 ; set the size to 768K
bra.s @EndSize
@Set512Ka move.b #Sonora512Ka,SonoraVRAMSize(a3) ; say that there<72>s 512K out there
bra.s @EndSize
@512Kb move.l #'768?',(a2) ; write signature to longword 0 in physbank 2
sub.l #4,(Sp) ; clear the data lines
add.l #4,(Sp)
cmp.l #'768?',(a2) ; if we got our signature back, then
beq.s @768Kb ; we<77>ve got expansion vRAM
move.b #Sonora512Kb,SonoraVRAMSize(a3) ; otherwise, there<72>s only 512K out there
bra.s @EndSize
@768Kb add.l #256*1024,d0 ; there must be 768K out there
cmp.l #'768?',SonoraWrap(a2) ; if we got our signature back, then
beq.s @Set768Kb ; it wrapped, so set 768K
bra.s @EndSize ; otherwise, there<72>s 1024K out there
@Set768Kb move.b #Sonora768Kb,SonoraVRAMSize(a3) ; say that there<72>s 768K out there
@EndSize lea (a0,d0.l),a1 ; point to end of video RAM (for end of Mod3 test)
moveq.l #0,D6
rts
@NotSonoraVideo
; From here to the <H11> above was added to support sizing Sonora VRAM. <SM6>end
CMPI.B #MSCDecoder,D0 ; do we have a MSC (DB-Lite)? <H4><SM6>
BNE.W @NotMSCVideo ; -> no <H4><SM6>
move.l #64*1024,D0 ; test this in 64k chunks <H18> to the next <H18><SM6>
MOVE.L VideoInfoPtr(A1),D1 ; get pointer to video info table <H4><SM6>
MOVEA.L (A1,D1.L),A0 ; get pointer to VRAM <H4><SM6>
LEA (A0,D0.L),A1 ; point to end also <H4><SM6>
addq.l #1,a4 ; bump the flag that tells us we've <SM6>
; already done this once <SM6>
beq.s @FinishMSCVideo ; have we tested the first 64k? <SM6>
add.l d0,a0 ; no, so bump the addresses to the <SM6>
lea (a0,d0.l),a1 ; second 64k chunk <H18><SM6>
@FinishMSCVideo
MOVEQ #0,D6 ; <H4>
RTS ; <H4>
@NotMSCVideo ; <H4>
CMPI.B #OrwellDecoder,D0 ; do we have an Orwell (Spike,Eclipse)? <H4>
BNE @NotOrwellVideo ; -> no <H4>
movea.l DAFBAddr(a0),a2 ;get the base address of the DAFB registers
lea @DAFBInit,a3 ;get the start address of the init table
moveq.l #0,d1 ;zero out the value register
bra.s @begin ;got start the process
@loop move.w (a3)+,d1 ;get the next value
move.l d1,(a2,d0.w) ;and write it to the register
@begin
move.w (a3)+,d0 ;get the next register offset
bpl.s @loop ;keep going if we're not at the end yet
movea.l VIA2Addr(a0),a3 ;get the VIA2 base address
btst.b #v2Speed,vBufB(a3) ;are we running at 33MHz?
beq.s @at25MHz ;branch if not
ori.l #dafb33MhzConfig,DAFB_Config(a2) ;otherwise, set up for 33MHz
@at25MHz
lea Clk_BaseOffset(a2),a3 ;offset to the clock registers
lea @DAFBClockChip,a4 ;and get a pointer to the setup parameters
moveq.l #0,d0 ;zero out a register
@loadClockLoop
move.b (a4)+,d0 ;get the next parameter
bmi.s @doneClockLoad ;done if we get -1
move.l d0,(a3) ;write it to the clock chip
lea $10(a3),a3 ;go to the next clock register
bra.s @loadClockLoop ;keep loading
@doneClockLoad
Move.l #dafbReleaseSwatch,DAFB_Reset(a2) ; Release swatch from reset.
bsr @DAFBResetDelay ; Wait for pullups.
Move.l #dafbReassertSwatch,DAFB_Reset(a2) ; Reset Swatch again.
bsr @DAFBResetDelay ; Wait for pullups.
Move.l #dafbReleaseSwatch,DAFB_Reset(a2) ; Release swatch from reset.
bsr @DAFBResetDelay ; Wait for pullups.
Move.l #dafbReleaseVRamSM,DAFB_Reset(a2) ; Reset VRam state machine.
bsr @DAFBResetDelay ; Wait for pullups.
Move.l #dafbReleaseVideoSM,DAFB_Reset(a2) ; Reset Video refresh state machine.
bsr @DAFBResetDelay ; Wait for pullups.
movea.l #DAFB_VRAM_Base,a3 ;brute force: get the VRAM base address!
moveq.l #0,d0 ;zero out total size of VRAM
move.l #'Shel',d1 ;get a reasonable signature
moveq.l #-1,d2 ;and something to discharge the bus
moveq.l #0,d6 ;success, so far ...
@sizeDAFBVram
lea (a3,d0.l),a4 ;get the start address of this bank
move.l d1,(a4) ;store the signature in VRAM
move.l d2,4(a4) ;make sure there's no ghost left
move.l d1,d3 ;make a copy of the signature
moveq.l #0,d4 ;zero out the byte lane bit mask
moveq.l #4-1,d5 ;4 bytes to check out
@nextByte
cmp.b (a4,d5.w),d3 ;is this byte lane good?
bne.s @byteBad ;don't continue if not
not.b d3 ;else, try the inverse pattern
not.b (a4,d5.w) ;in both locations
move.l d2,4(a4) ;make sure there's no ghost left
cmp.b (a4,d5.w),d3 ;does this add up?
beq.s @byteGood ;branch if good
@byteBad
bset.l d5,d4 ;else, mark this byte lane bad
@byteGood
ror.l #8,d3 ;get the next byte
dbra.w d5,@nextByte ;loop until all byte lanes have been checked
cmp.b #$f,d4 ;was this location totally bad?
beq.s @cleanup ;we're done if so
rol.l #4,d6 ;accumulate the bad byte lane masks from d4
or.b d4,d6 ;accumulate the bad byte lane mask
move.l d2,(a3,d0.l) ;else, nix signature in VRAM
add.l #DAFB_BankSize,d0 ;otherwise, we have another bank
cmp.l #DAFB_BankSize*4,d0 ;is this the max?
bne.s @sizeDAFBVram ;keep going if not
@cleanup movea.l a3,a0 ;else, put the base of VRAM here
lea (a0,d0.l),a1 ;and put the end of VRAM here
RTS ; <H4>
; this table is a set of hardware values to write to DAFB before it will work:
;
; register value
@DAFBInit dc.w DAFB_Reset, 7 ;reset the chip
dc.w DAFB_VidBaseHi, 8 ;base address hi word
dc.w DAFB_VidBaseLo, 0 ;base address lo word
dc.w DAFB_RowWords, 100 ;row words
dc.w DAFB_ClkCfg, 1538 ;DAFB clock configuration register
dc.w DAFB_Config, 80 ;DAFB configuration register
dc.w Swatch_Mode, 4082
dc.w Swatch_TimeAdj, 142
dc.w Swatch_HSerr, 798
dc.w Swatch_Hlfln, 432
dc.w Swatch_HEq, 32
dc.w Swatch_HSP, 863
dc.w Swatch_HBWay, 63
dc.w Swatch_HBrst, 75
dc.w Swatch_HBP, 111
dc.w Swatch_HAL, 152
dc.w Swatch_HFP, 792
dc.w Swatch_HPix, 862
; Swatch vertical sync registers (set as a group)
dc.w Swatch_VHLine, 1050 ; VHLine
dc.w Swatch_VSync, 1048 ; VSync
dc.w Swatch_VBPEq, 4 ; VBPEq
dc.w Swatch_VBP, 9 ; VBP
dc.w Swatch_VAL, 82 ; VAL
dc.w Swatch_VFP, 1042 ; VFP
dc.w Swatch_VFPEq, 1046 ; VFPEq
dc.w ACDC_ConfigReg, 152 ; ACDC offset from DAFBBase
dc.w -1 ;end of this table
@DAFBClockChip
dc.b 15
dc.b 7
dc.b 0
dc.b 0
dc.b 5
dc.b 1
dc.b 0
dc.b 0
dc.b 0
dc.b 2
dc.b 5
dc.b 6
dc.b 4
dc.b 1
dc.b 0
dc.b 0
dc.b -1
align
@DAFBResetDelay ; this quick and dirty routine assures the minimum
Nop ; wait period between successive accesses to the
Nop ; DAFB_reset register
Nop
Nop
Nop
Nop
Nop
Nop
rts
@NotOrwellVideo
ENDWITH
MOVEQ #-1,D6 ; this decoder doesn't support dedicated VRAM
RTS
;From here to the next <T8> above was added to implement a VRAM sizing routine
;which works on the mac LC, TIM, Eclipse, Spike, DB-Lite, ...
;From here to the next <23> below was added for the new V8 video RAM test
TestVRAM
;-----------------------------------------------------------------------------
;
; #97: VRAM test
; This tests the video RAM which is controlled by the V8 ASIC. The test
; sizes video RAM, then calls the mod3test, revmod3test and the extramtest
; on video RAM.
;
; Inputs: a0 - decoder info record
; a1 - product info record
;
; Ouputs: d6 - result
;
; Destroys: all registers except sp
;
;-----------------------------------------------------------------------------
move.l a6,-(sp) ;put the return address on the stack <T8><SM6>begin
move.l a4,-(sp) ;preserve a4 across this test <H18> to the next <H18>
; If we're running an MSC decoder, we need to test GSC VRAM in two 64k chunks
; because memory isn't contiguous for the current DBLite STN screen. So, we'll
; keep a flag around telling whether both chunks have been tested or not. Ugly
; to be sure, but the only other solution is setting the GSC to think that it's
; talking to a TFT screen in 4-bit mode. However, this doesn't work because
; after saving and restoring the GSC registers, the OS is not able to properly
; init the screen; it comes up twisted on a cold boot after trying to do that:
WITH DecoderKinds, DecoderInfo, ProductInfo ;
cmpi.b #MSCDecoder,ProductInfo.DecoderKind(a1)
bne.s @notMSCDecoder
move.l #-1,a4 ;use this as the flag
movea.l DecoderInfo.VDACAddr(a0),a2 ;point to base of gsc
move.b GSCGrayScale(a2),d0 ;get the current setting of this reg.
move.b d0,-(sp) ;save it for later restoration
and.b #$DF,d0 ;clear the Display Blank bit
move.b d0,GSCGrayScale(a2) ;and blank the screen
; OK, so it's not an MSC decoder. Fine. However, we do need to determine if we're <H20>
; on a Sonora so that we can save and restore the VRAM sizing info: <H20>
@notMSCDecoder ; <H20>
cmpi.b #SonoraDecoder,ProductInfo.DecoderKind(a1) ;do we have Sonora (Vail)? <H20>
bne.s @Begin ;no, so continue <H20>
move.l VIA1Addr(a0),a3 ;use the DecoderInfo ptr to get to the via1 base <H20>
adda.l #SonoraVIA2Base,a3 ;from there, get the VIA2 base <H20>
move.b SonoraVRAMSize(a3),d0 ;and save the current VRAM size <H20>
move.b d0,-(sp) ;for later restoration <H20>
@Begin ; <H20>
movem.l a0/a1,-(sp) ;save these
bsr SizeVRAM ;go size VRAM <T8>
movem.l (sp)+,a2/a3 ;restore them here (a0 & a1 now set for Mod3) <H18>
cmp.l #-1,d6 ;does this apply? <T8>
beq.l @noVRAM ;exit if not <T8><H11>
tst.l d0 ;else, do we have any VRAM anyway? <T8>
beq.l @noVRAM ;exit if not <T8><H11>
cmpi.b #OrwellDecoder,DecoderKind(a3) ;is this a DAFB? <T8><H18>
ENDWITH ; <SM6>end
bne.s @normalTest ;continue if not <T8>
movea.l a1,a2 ;save this for later <T8>
movea.l a0,a1 ;set this up for starters <T8>
moveq.l #0,d2 ;init the failed bit mask to zero <T8>
@DAFBVRAMTestLoop
movea.l a1,a0 ;the old end address is the new start address<T8>
adda.l #DAFB_BankSize,a1 ;the new end address is the end of the next bank<T8>
rol.w #4,d2 ;make room for this bank's error bits <T8>
moveq.l #0,d6 ;zero out the results register <T8>
movem.l d2/a2,-(sp) ;save some local registers <T8>
BSR6 Mod3Test ;go test VRAM <T8>
movem.l (sp)+,d2/a2 ;and restore our regs <T8>
tst.l d6 ;how did this bank look? <T8>
beq.s @StillOK ;continue if it was OK <T8>
moveq.l #4-1,d3 ;otherwise, construct the failed byte lane mask<T8>
@SetBits
tst.b d6 ;was there a problem in this byte lane? <T8>
beq.s @continue ;continue if not <T8>
bset.l d3,d2 ;else, indicate the problem <T8>
@continue
ror.l #8,d6 ;go to the next byte lane failed bit mask <T8>
dbra.w d3,@SetBits ;and keep going 'till done <T8>
@StillOK
cmpa.l a1,a2 ;are we done yet? <T8>
bne.s @DAFBVRAMTestLoop ;keep going if not <T8>
move.l d2,d6 ;put the failed mask into the result reg <T8>
bra.s @EndTest ;then exit <T8>
@normalTest ; <T8>
movem.l a2/a3,-(sp) ;save the product & decoder info ptrs <H18><SM6>
moveq.l #0,d6 ;zero out the results register
BSR6 Mod3Test ;perform the mod 3 RAM test
tst.l d6 ;Any errors?
bne.s @EndTest ;Error out if so
BSR6 RevMod3Test ;perform the reverse mod 3 RAM test
; <28>
@EndTest ; <H18><SM6>begin
movem.l (sp)+,a0/a1 ;restore the product & decoder info ptrs
WITH DecoderKinds, DecoderInfo, ProductInfo;
cmpi.b #MSCDecoder,DecoderKind(a1)
bne.s @stillNotMSCDecoder
cmp.l #1,a4 ;see if we've tested both chunks of GSC VRAM
beq.s @GSCRestore ;yes, so finish up
movem.l a0/a1,-(sp) ;save these across SizeVRAM
bsr SizeVRAM ;go size VRAM again (get the second 64k)
movem.l (sp)+,a2/a3 ;restore the product & decoder info ptrs here
bra.s @normalTest ;and test it
@GSCRestore
movea.l VDACAddr(a0),a5 ;point to base of gsc
move.b (sp)+,GSCGrayScale(a5) ;and restore this register
bra.s @Done ;then leave
ENDWITH ;
@stillNotMSCDecoder ; <H18>
; Restore the Sonora VRAM sizing info, if applicable: <H20>
WITH DecoderKinds, DecoderInfo, ProductInfo ; <H11>
cmpi.b #SonoraDecoder,DecoderKind(a1) ; do we have Sonora (Vail)? <H11>
bne.s @Done ; -> no <H11><H18>
move.l VIA1Addr(a0),a3 ; use the DecoderInfo ptr to get to the via1 base <H11>
adda.l #SonoraVIA2Base,a3 ; from there, get the VIA2 base <H11>
move.b (sp)+,d0 ; restore the original VRAM sizing info <H20>
move.b d0,SonoraVRAMSize(a3) ; from what was saved prior to the test <H11><H20>
ENDWITH ; <H11>
@Done ; <H11><H12>
move.l (sp)+,a4 ;restore a4 <H18><SM6>end
rts ;and return <24>
@noVRAM
moveq.l #-1,d6 ;Indicate that test does not apply
move.l (sp)+,a4 ;restore a4 <H18><SM6>
rts ;and return to caller <T8>
;-------------------------------------------------------------------------------
;
; This tests the 53C96 chip(s). Note that a terminator is required for this
; test to work.
;
; This tests the registers of the chip and is still in a state of developement
;
;-------------------------------------------------------------------------------
TestC96
WITH DecoderInfo
move.l a6,-(sp) ;put the return address on the stack
btst.l #SCSI96_1Exists,d0 ;Do we have a SCSI 1 bus?
bne.s @TestSCSI1 ;go test the chip if so
btst.l #SCSI96_2Exists,d0 ;else, do we have a SCSI 2 bus?
bne.s @TestSCSI2 ;go test it if so
moveq.l #-1,d6 ;else, exit with a "test does not apply" status
rts ;and return
@TestSCSI1
movea.l SCSI96Addr1(a0),a2 ;get the base address of SCSI 1
bsr.s TestC96Chip ;and go test the chip
bne.s @Done ;exit if error!
btst.l #SCSI96_2Exists,d0 ;done testing bus #1, do we have a second one?
beq.s @Done ;exit if we don't
@TestSCSI2
movea.l SCSI96Addr2(a0),a2 ;get the base address of SCSI 2
bsr.s TestC96Chip ;and go test the chip
beq.s @Done ;exit if success
bset.l #31,d6 ;else, indicate SCSI 2 failure
ENDWITH
@Done
rts
savedregs reg d0-d3 ;registers to save
;---------------------------------------------------------------------------
;
; This tests the functionality of the 53C96 SCSI chip. If there is an error,
; the upper byte of D6 will contain an error from the following table:
;
SCSIErrs RECORD 1,INCREMENT
XfrCntLSBError ds.b 1 ;LSB of xfr counter mismatched (expected,actual)
XfrCntMSBError ds.b 1 ;MSB of xfr counter mismatched (expected,actual)
FIFOResetError ds.b 1 ;FIFO not zero after reset (none)
FIFORegFillErr ds.b 1 ;error filling FIFO using byte accesses to register (expected, actual byte count)
FIFORegCmpErr ds.b 1 ;error in FIFO data doing a byte compare to register (FIFO status,expected,actual)
FIFORegEmtyErr ds.b 1 ;FIFO not empty after emptying it with byte reads to register (fifo status bits)
FIFOBitWalkErr ds.b 1 ;error doing a FIFO bit walk (FIFO status, expected, actual)
CF1RegError ds.b 1 ;compare error on configuration register 1 (expected, actual)
CF2RegError ds.b 1 ;compare error on configuration register 2 (expected, actual)
CF3RegError ds.b 1 ;compare error on configuration register 3 (expected, actual)
ENDR
;
;
;---------------------------------------------------------------------------
WITH SCSIErrs
TestC96Chip
movem.l savedregs,-(sp) ;save some registers
move.b #cRstSChp,rCMD(a2) ;reset the SCSI chip first
moveq.l #0,d6 ;clear the result register
;
; First we test the counter value. The counter registers are writable, but when
; read they return the actual count value, not the load/reload value. We must
; execute a DMA NOP command to load the count reload value into the actual counter.
; then we can verify that the value got in there.
;
moveq.l #0,d0 ;start with zero
@XfrCntLoop
move.b d0,rXCL(a2) ;load the low byte
ror.w #8,d0 ;get the next byte
move.b d0,rXCM(a2) ;and load the high byte
ror.w #8,d0 ;restore d0
move.b #($80|cNOP),rCMD(a2) ;send a DMA NOP
move.b rXCM(a2),d1 ;get the MSB
asl.w #8,d1 ;put it in the high byte
move.b rXCL(a2),d1 ;get the LSB
cmp.w d0,d1 ;do we have a match?
bne.w @XfrCntFailure ;error out if not
addq.l #5,d0 ;increment the test value
cmp.l #$FFFF,d0 ;are we over?
ble.s @XfrCntLoop ;continue if not
;
; Next, test the FIFO
;
move.b #FIFOResetError,d6 ;assume a FIFO reset error
swap d6 ;move it to the high word
asl.l #8,d6 ;move it to the high byte
move.b rFOS(a2),d0 ;read the FIFO flags register
and.b #iFOFMsk,d0 ;and out the FIFO flags
bne.w @ErrorExit ;error out if not zero
; FIFO is empty - try filling it using byte transfers to the FIFO register
move.w #iFifoSize-1,d0 ;initialize counter
@FIFOByteFill
move.b d0,rFFO(a2) ;move value to FIFO
dbra.w d0,@FIFOByteFill ;continue until full
move.b #FIFORegFillErr,d6 ;assume a FIFO byte fill error
move.b rFOS(a2),d0 ;get the FIFO flags reg
and.b #iFOFMsk,d0 ;and out the FIFO fill status
cmp.b #iFifoSize,d0 ;do we have our fill?
bne.w @FIFOFillError ;error out if so
move.w #iFifoSize-1,d0 ;prepare to compare values in FIFO
move.b #FIFORegCmpErr,d6 ;assume a compare error
@FIFOByteCompare
move.b rFFO(a2),d1 ;get a byte from the FIFO
cmp.b d0,d1 ;do we compare OK?
dbne.w d0,@FIFOByteCompare ;continue if OK
bne.w @FIFOCompareError ;error out if we had a mismatch
move.b #FIFORegEmtyErr,d6 ;assume an error
move.b rFOS(a2),d0 ;is the FIFO now empty?
and.b #iFOFMsk,d0 ;get the FIFO fill status
bne.w @FIFOEmptyError ;error out if not empty
; FIFO is empty again - now to test the FIFO for pattern sensitivity
move.w #iFifoSize-1,d2 ;get the fifo size
moveq.l #1,d0 ;init a bit position
@BitWalkFill
move.b d0,rFFO(a2) ;put the pattern into the fifo
rol.b #1,d0 ;rotate it left
dbra.w d2,@BitWalkFill ;and continue to fill the FIFO
move.w #iFifoSize-1,d2 ;get the fifo size
moveq.l #1,d0 ;init a bit position
move.b #FIFOBitWalkErr,d6 ;get the error code
@BitWalkCmpr
move.b rFFO(a2),d1 ;read the FIFO
cmp.b d0,d1 ;are we equal?
bne.s @FIFOCompareError ;branch out if not
rol.b #1,d0 ;else get the next value
dbra.w d2,@BitWalkCmpr ;and continue
; FIFO is now empty again - now to test some other registers:
; configuration registers 1 through 3 - all bits read/write
move.w #256*3,d2 ;initialize a loop constant
moveq.l #0,d0 ;and init a write value
@ConfigRegTest
move.b d0,rCF1(a2) ;write a value to configuration register 1
addq.l #1,d0 ;increment write value
move.b d0,rCF2(a2) ;write different value to configuration register 2
addq.l #1,d0 ;increment value
move.b d0,rCF3(a2) ;write different value to CF reg 3
subq.l #2,d0 ;get back to the original write value
move.b rCF1(a2),d1 ;read back CF reg 1
cmp.b d0,d1 ;are we equal?
bne.s @CF1Error ;exit if not
addq.l #1,d0 ;increment write reg
move.b rCF2(a2),d1 ;this should equal d0 now
move.b d0,d3 ;save d0
and.b #$DF,d0 ;get the valid bits
cmp.b d0,d1 ;are we equal?
bne.s @CF2Error ;branch if not
move.b d3,d0 ;restore d0
addq.l #1,d0 ;increment d0 again
move.b rCF3(a2),d1 ;get the next register's value
move.b d0,d3 ;save original value
and.b #7,d0 ;only low 3 bits are valid for CF3
cmp.b d0,d1 ;are we equal?
bne.s @CF3Error ;exit if not
move.b d3,d0 ;else, restore d0
addq.l #1,d0 ;go on now
dbra.w d2,@ConfigRegTest ;and continue
moveq.l #0,d6 ;if we made it this far, we must have succeeded
bra.s @Exit ;exit out
;
; Errors:
;
; failure of the transfer count register
@XfrCntFailure
move.b #XfrCntLSBError,d6 ;this in the high byte means LSB mismatch
cmp.b d0,d1 ;is this the case?
bne.s @FndMisMatch ;exit if so
move.b #XfrCntMSBError,d6 ;this int he high byte means MSB mismatch
ror.w #8,d0 ;get the high bytes
ror.w #8,d1 ;in the actual and expected registers
@FndMisMatch
swap d6 ;put error code in high word
move.b d0,d6 ;put expected value in LSB
asl.l #8,d6 ;move it up
move.b d1,d6 ;put actual value next
bra.s @ErrorExit ;exit immediately
;
; failure to fill the FIFO error
;
@FIFOFillError
swap d6 ;move it to the high word
move.b #iFifoSize,d6 ;indicate expected bytes in FIFO
asl.l #8,d6 ;move it up
move.b d0,d6 ;place actual bytes in FIFO
bra.s @ErrorExit ;exit
;
; FIFO compare error
;
@FIFOCompareError
asl.l #8,d6 ;move error code up
move.b rFOS(a2),d6 ;store the FIFO status value next
asl.l #8,d6 ;move it up
move.b d0,d6 ;store the expected value in the next byte
asl.l #8,d6 ;move it up
move.b d1,d6 ;then store the actual value read
bra.s @ErrorExit ;exit
;
; FIFO not empty error
;
@FIFOEmptyError
swap d6 ;move it into the high word
asl.l #8,d6 ;shift it up
move.b d0,d6 ;store actual residual in FIFO
bra.s @ErrorExit ;error out
; compare error on a configuration register
@CF1Error
move.b #CF1RegError,d6 ;compare error on CF reg 1
bra.s @CFError
@CF2Error
move.b #CF2RegError,d6 ;compare error on CF reg 2
bra.s @CFError
@CF3Error
move.b #CF3RegError,d6 ;compare error on CF reg 3
@CFError
swap d6 ;move error code to high word
move.b d0,d6 ;get the expected value
asl.l #8,d6
move.b d1,d6 ;and get the actual value
;;; bra.s @ErrorExit
@ErrorExit
@Exit
move.b #cRstSChp,rCMD(a2) ;reset the SCSI chip again
movem.l (sp)+,savedregs ;restore registers
tst.l d6 ;return with Z bit reflecting error condition
rts
ENDWITH
TestGSCRegs
;-------------------------------------------------------------------------------
; Routine: #XX: TestGSCRegs
;
; Inputs: a0 - ptr to table of hardware base addresses
; a1 - ptr to product information table
; a6 - return address
;
; Outputs: d6 - 0 if test passes, fail code if not. The code is as follows:
;
; high byte: zero
; next byte: failing register (offset from VDACAddr)
; next byte: expected value
; low byte: actual value
;
; Destroys: a2, a3, a4, d1, d2, d3, d4, d5, d6 <H13>
;
; This routine does bitwalks (a cycle of zeros first, then a cycle of ones) over the
; various read/write registers in the GSC (Gray Scale Chip) used in DBLite and
; probably future portables. These registers are:
;
; <09> (R2) Panel ID Control <09> (R3) Panel Setup
; <09> (R4) Gray Scale <09> (R5) Polynomial
; <09> (R6) Panel Adjust <09> (R7) ACDCLK
; <09> (R8) Refresh Rate <09> (R9) Blank Shade
; <09> (Ra) Panel Skew
;
; Note: Registers R0 and R1 are read only, ergo they aren't tested (or should they
; be?).
;
; For each register, I'll save the current value (in case it happens to be holding
; legitimate and needed data when this test is run), thrash it, then restore the
; value. I'll also blank the screen for these tests, since it might not be pretty.
;-------------------------------------------------------------------------------
invertVideo equ $80 ; tells the Panel Adjust register to invert video <H13><SM6>
grayShade equ $0f ; tells the Blank Shade register to use this shade <H13><SM6>
blankDisplay equ $00 ; tells the Gray Scale reg. to blank the screen <H13><SM6>
resetVINT equ $80 ; tells the Gray Scale reg. to reset the VINT flag <H13><SM6>
move #0,CCR ; clear the extend bit to prepare for a zero walk <H13><SM6>
moveq #0,d6 ; just in case ; <H13>v
; get current screen blanking info and save it, then blank the screen for this routine
moveq #0,d2 ; <H13><SM6>
move.l DecoderInfo.VDACAddr(a0),a2 ;Get GSC base address
move.b GSCGrayScale(a2),d2 ; get the Gray Scale register to low byte of d2
lsl.l #8,d2 ; free up the low byte for Blank Shade reg. <H13><SM6>
move.b GSCBlankShade(a2),d2 ; get the Blank Shade register <H13><SM6>
lsl.l #8,d2 ; free up the low byte for Panel Adjust reg. <H13><SM6>
move.b GSCPanelAdj(a2),d2 ; get the Panel Adjust register
move.l d2,-(sp) ; save the current screen blanking info
; blank the screen by setting the following registers to these values:
; Panel Adjust = % 1xxxxxxx
; Blank Shade = % xxxx1111
; Gray Scale = % 00000000
or.b #invertVideo,GSCPanelAdj(a2) ; <H13><SM6>
or.b #grayShade,GSCBlankShade(a2) ; <H13><SM6>
move.b #blankDisplay,GSCGrayScale(a2) ; <H13><SM6>
; begin test sequence
;<3B><><EFBFBD>
;<3B><><EFBFBD><EFBFBD>
;
; NOTE: Determine how to tell what the state of the X bit in the ccr is going to be! The
; TestRBV routine seems to assume that it will start out being zero, but there are
; no guarantees on this, especially if the float tests have been run (which may or
; may not affect the X bit)!!!!! Figure out how to set it to zero if I need to!!
;
; AARON AARON AARON
;
;move.b ccr,d1 ; I need to make sure that the X bit is clear
;and.b #$ef,d1 ; before starting this test, becuase it's used
;move.b d1,ccr ; to walk 0's and 1's
lea GSCRegOffsets,a3 ; the table of GSC register offsets from VDACAddr
lea GSCRegMasks,a4 ; the table of masks for each register
; start by walking a zero across the register
@GSCOneLoop
moveq #0,d1 ; used to hold the register offset value <H13><SM6>
move.b (a3)+,d1 ; get the register to be tested
bmi @GSCZero ; all finished if register offset is -1 (end of table) <H13><SM6>
move.b (a4)+,d2 ; get the mask that corresponds to this reg
moveq #-1,d3 ; this is the test data (to write 1's)
move.b (a2,d1.w), -(sp) ; save the real value in this register
@InnerOneLoop ; <H13><SM6>
move.b d3,d4 ; save a copy of the test data
and.b d2,d3 ; mask out the read only bits of this register
move.b d3,(a2,d1.w) ; write the "adjusted" test value into the reg
moveq #0,d5 ; clear the bus of stray values <H13><SM6>
move.b (a2,d1.w),d5 ; read the register
and.b d2,d5 ; mask out the read only bits
cmp.b d3,d5 ; compare written value to read value
bne @GSCError ; if there's an error, record it and continue
move.b d4,d3 ; get back the original test data
roxr.b #1,d3 ; walk a zero across the entire register
cmp.b #-1,d3 ; finished (has the 0 walked thru back to the
; x bit)?
bne.s @InnerOneLoop ; no, so keep walking the bits <<from here to the <H13> below>><SM6>begin
move.b (sp)+,(a2,d1.w) ; this register is done, so restore its original value
bra.s @GSCOneLoop ; and move on to the next one
; now do the same thing, but walk a 1 across the registers
@GSCZero
lea GSCRegOffsets,a3 ; the table of GSC register offsets from VDACAddr
lea GSCRegMasks,a4 ; the table of masks for each register
@GSCZeroLoop
moveq #0,d1 ; used to hold the register offset value
move.b (a3)+,d1 ; get the register to be tested
bmi @GSCDone ; all finished if register offset is -1 (end of table)
move.b (a4)+,d2 ; get the mask that corresponds to this reg
roxr.b #1,d3 ; rotate a one into the extend bit (d3 was left at $ff after
; the zero walk above)
clr.b d3 ; clear out the test data register (start w/ all zeros)
move.b (a2,d1.w), -(sp) ; save the real value in this register
@InnerZeroLoop
move.b d3,d4 ; save a copy of the test data
and.b d2,d3 ; mask out the read only bits of this register
move.b d3,(a2,d1.w) ; write the "adjusted" test value into the reg
moveq #0,d5 ; clear the bus of stray values <<from here to the <H13> above>><SM6>end
move.b (a2,d1.w),d5 ; read the register
and.b d2,d5 ; mask out the read only bits
cmp.b d3,d5 ; compare written value to read value
bne @GSCError ; if there's an error, record it and continue
move.b d4,d3 ; get back the original test data
roxr.b #1,d3 ; walk a one across the entire register
bne @InnerZeroLoop ; keep going until finished (or error) <H13><SM6>
move.b (sp)+,(a2,d1.w) ; this register is done, so restore its original value <H13><SM6>
bra.s @GSCZeroLoop ; all finished, and no error, so restore the <H13><SM6>
; screen and quit this test
@GSCError ; log the error that occurred
move.b (sp)+,(a2,d1.w) ; this register was being worked on when the error came <H13><SM6>
; up, so restore its original value <H13><SM6>
move.b d1,d6 ; get the offending register (offset value)
rol.l #8,d6 ; make room for the expected data
move.b d3,d6 ; move it into the returned error
rol.l #8,d6 ; make room for the actual data
move.b d5,d6 ; move it into the returned error
@GSCDone ; restore the state of the machine and quit
move.l (sp)+,d2 ; get the saved info <H13><SM6>
move.b d2,GSCPanelAdj(a2) ; and restore it in the reverse order it was saved
ror.l #8,d2 ; <H13><SM6>
move.b d2,GSCBlankShade(a2)
ror.l #8,d2 ; <H13><SM6>
move.b #resetVINT,GSCGrayScale(a2) ; this is necessary because there may be a pending VINT <H13><SM6>
; interrupt that needs to be cleared or we'll hang the video <H13><SM6>
move.b d2,GSCGrayScale(a2)
; return to the caller with d6 containing any error codes
RTS6
; Some of the GSC registers only have a few bits defined, with the others reserved
; to zero. Others have all bits read/write. Therefore, these tables were created for
; each to hold masks with the reserved bits cleared and the read/write bits set
; (for the walking 1's test), and the opposite for the walking zeros test.
; Also, a table of register offsets is used to step through all of the registers:
GSCRegOffsets dc.b $02, $05, $06, $07, $08, $09, $0a, $ff ; end of table marker <H13><SM6>
GSCRegMasks dc.b $07, $ff, $b8, $ff, $0f, $0f, $ff ; <H13><SM6>
align
; End of TestGSCRegs
;-------------------------------------------------------------------------------
PGESelfTest
;-------------------------------------------------------------------------------
; Routine: #XX: PGESelfTest
;
; Inputs: a0 - ptr to table of hardware base addresses
; a1 - ptr to product information table
; a6 - return address (called by BSR6)
;
; Outputs: d6 - <H17> to the one below
; $00xx 0000 = the return value from the PG&E self test (if there was
; no problem communicating with PG&E), as follows:
; 1 ROM checksum failed
; 2 RAM addressing failure
; 3 RAM data retention failure
;
; $0000 00xx = whatever error code was returned by PG&E in response
; to a request (could not communicate with PG&E)
;
;
; Destroys: a2, a5, a6, d3, d4, d5 <H17>
;
; This routine causes PG&E (the power management ASIC on DBLite and probably other
; machines) to execute its self test by issuing a USTPMgrSendCommand (note that it is
; necessary for a0 to be set up correctly for this call). Any failures will be returned
; by this routine through d6. At the time of this writing, the self test consists of
; the following:
;
; <09> a checksum
; <09> an address test
; <09> a data test (non-destructive RAM test)
;
; A destructive RAM test will be implemented later. I will make sure to save off
; the PG&E data and restore it after the self test is over. That way, as PG&E is
; revved, this routine should not have to change at all.
;-------------------------------------------------------------------------------
move.w sr,-(sp) ; preserve the status register <H13><SM6>
move.l a6,-(sp) ; save return address <H13><H17><SM6>
ori.w #hiIntMask,sr ; turn interrupts off <H13><SM6>
moveq #0,d6 ; just in case
move.w #$00EC,d3 ; command=$EC, length=0 <H17> to the one below
BSR6 USTPMgrSendCommand ; send the command to the PMGR <SM6>
bne.s @Done ; -> error <SM6>
move.l #65,d5 ; loop this many times trying to get the response <SM6>
@retryLoop
BSR5 USTPMgrRecvByte ; get the response byte in D3 <SM6>
dbeq d5,@retryLoop ; yes, we timed out so try again <SM6>
bne.s @Done ; we've allowed about 2 seconds, so bail <SM6>
; The result is already in d6, so just shift it up into high word so the user
; can differentiate between a PMgr error and a PMgr return value:
@returnResults
move.b d3,d6 ; no PMGR command problems, so get the <SM6>
; result of the self test in d6 <SM6>
swap d6 ; move the low byte into the high word <SM6>
@Done
move.l (sp)+,a6 ; restore return address <H13><H17><SM6>
move.w (sp)+,sr ; restore interrupt level <H13><SM6>
RTS6 ; return to the caller
; End of PGESelfTest
;-------------------------------------------------------------------------------
TestCSCRegs
;-------------------------------------------------------------------------------
; Routine: #A0: TestCSCRegs
;
; Inputs: a0 - ptr to table of hardware base addresses
; a1 - ptr to product information table
; a6 - return address
;
; Outputs: d6 - 0 if test passes, fail code if not. The code is as follows:
;
; high byte: zero
; next byte: failing register (offset from VDACAddr)
; next byte: expected value
; low byte: actual value
;
; Destroys: a2, a3, a4, d1, d2, d3, d4, d5, d6
;
; This routine does bitwalks (a cycle of zeros first, then a cycle of ones) over the
; various read/write registers in the CSC (Color Support Chip) used in Escher and
; probably future portables. These registers are:
;
; <09> (R6) Panel Type <09> (R12) Display Format
; <09> (R8) Panel Setup <09> (R16) Refresh Rate
; <09> (Ra) Output Format <09> (R1c) Horz Skew Low
; <09> (Rc) FRC Control <09> (R28) LP Start
; <09> (Re) M Adjust <09> (R2a) LP Width
; <09> (R10) N Adjust <09> (R2c) FLM Control
;
; For each register, I'll save the current value (in case it happens to be holding
; legitimate and needed data when this test is run), thrash it, then restore the
; value. I'll also blank the screen for these tests, since it might not be pretty.
;-------------------------------------------------------------------------------
;invertVideo set $80 ; tells the Panel Adjust register to invert video
TestpwrDown set $fe ; Clearing bit 0 Drives PNLPWR Low and disables panel Drivers
;blankDisplay set $fb ; tells the Display Status reg. to blank the screen
;resetVINT set $02 ; tells the Display Status reg. to reset the VINT flag
move #0,CCR ; clear the extend bit to prepare for a zero walk
moveq #0,d6 ; just in case ;
; get current screen blanking info and save it, then blank the screen for this routine
moveq #0,d2 ;
move.l DecoderInfo.VDACAddr(a0),a2 ;Get CSC base address
move.b CSCPanelSetup(a2),d2 ; get the Panel Setup register to low byte of d2
lsl.l #8,d2 ; free up the low byte for Display Status reg.
move.b CSCDisplayStatus(a2),d2 ; get the Blank Shade register
move.l d2,-(sp) ; save the current screen blanking info
; blank the screen
or.b #invertVideo,CSCPanelsetup(a2) ;
and.b #TestpwrDown,CSCPanelsetup(a2) ;
and.b #blankDisplay,CSCDisplayStatus(a2) ;
; begin test sequence
lea CSCRegOffsets,a3 ; the table of CSC register offsets from VDACAddr
lea CSCRegMasks,a4 ; the table of masks for each register
; start by walking a zero across each of the registers
@CSCOneLoop
moveq #0,d1 ; used to hold the register offset value
move.b (a3)+,d1 ; get the register to be tested
bmi @CSCZero ; all finished if register offset is -1 (end of table)
move.b (a4)+,d2 ; get the mask that corresponds to this reg
moveq #-1,d3 ; this is the test data (to write 1's)
move.b (a2,d1.w), -(sp) ; save the real value in this register
@InnerOneLoop ;
move.b d3,d4 ; save a copy of the test data
and.b d2,d3 ; mask out the read only bits of this register
move.b d3,(a2,d1.w) ; write the "adjusted" test value into the reg
moveq #0,d5 ; clear the bus of stray values
move.b (a2,d1.w),d5 ; read the register
and.b d2,d5 ; mask out the read only bits
cmp.b d3,d5 ; compare written value to read value
bne @CSCError ; if there's an error, record it and continue
move.b d4,d3 ; get back the original test data
roxr.b #1,d3 ; walk a zero across the entire register
cmp.b #-1,d3 ; finished (has the 0 walked thru back to the
; x bit)?
bne.s @InnerOneLoop ; no, so keep walking the bits
move.b (sp)+,(a2,d1.w) ; this register is done, so restore its original value
bra.s @CSCOneLoop ; and move on to the next one
; now do the same thing, but walk a 1 across the registers
@CSCZero
lea CSCRegOffsets,a3 ; the table of GSC register offsets from VDACAddr
lea CSCRegMasks,a4 ; the table of masks for each register
@CSCZeroLoop
moveq #0,d1 ; used to hold the register offset value
move.b (a3)+,d1 ; get the register to be tested
bmi @CSCDone ; all finished if register offset is -1 (end of table)
move.b (a4)+,d2 ; get the mask that corresponds to this reg
clr.b d3
roxr.b #1,d3 ; rotate a ZERO into the extend bit
move.b #$80,d3 ; Start with bit 7
move.b (a2,d1.w), -(sp) ; save the real value in this register
@InnerZeroLoop
move.b d3,d4 ; save a copy of the test data
and.b d2,d3 ; mask out the read only bits of this register
move.b d3,(a2,d1.w) ; write the "adjusted" test value into the reg
moveq #0,d5 ; clear the bus of stray values
move.b (a2,d1.w),d5 ; read the register
and.b d2,d5 ; mask out the read only bits
cmp.b d3,d5 ; compare written value to read value
bne @CSCError ; if there's an error, record it and continue
move.b d4,d3 ; get back the original test data
roxr.b #1,d3 ; walk a one across the entire register
bne @InnerZeroLoop ; keep going until finished (or error)
move.b (sp)+,(a2,d1.w) ; this register is done, so restore its original value
bra.s @CSCZeroLoop ; all finished, and no error, so restore the
; screen and quit this test
@CSCError ; log the error that occurred
move.b (sp)+,(a2,d1.w) ; this register was being worked on when the error came
; up, so restore its original value
move.b d1,d6 ; get the offending register (offset value)
rol.l #8,d6 ; make room for the expected data
move.b d3,d6 ; move it into the returned error
rol.l #8,d6 ; make room for the actual data
move.b d5,d6 ; move it into the returned error
@CSCDone ; restore the state of the machine and quit
move.l (sp)+,d2 ; get the saved info
move.b d2,CSCDisplayStatus(a2) ; and restore it in the reverse order it was saved
ror.l #8,d2 ;
move.b d2,CSCPanelSetup(a2)
or.b #resetVINT,CSCDisplayStatus(a2) ; this is necessary because there may be a pending VINT
; interrupt that needs to be cleared or we'll hang the video
; return to the caller with d6 containing any error codes
RTS6
; Some of the CSC registers only have a few bits defined, with the others reserved
; to zero. Others have all bits read/write. Therefore, these tables were created for
; each to hold masks with the reserved bits cleared and the read/write bits set
; (for the walking 1's test), and the opposite for the walking zeros test.
; Also, a table of register offsets is used to step through all of the registers:
CSCRegOffsets dc.b $06, $08, $0A, $0C, $0E, $10, $12, $16, $1C, $28, $2A, $2C, $ff ; end of table marker
CSCRegMasks dc.b $07, $07, $07, $07, $07, $07, $07, $07, $07, $07, $07, $07 ;
; End of TestCSCRegs
;-------------------------------------------------------------------------------
ENDPROC