mac-rom/OS/StartMgr/USTNonCritTsts.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

6767 lines
256 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; 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: © 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.
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; Pre-HORROR ROM comments begin here.
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; <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.
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; Pre-TERROR ROM comments begin here.
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; <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
; ­0, ­-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Õ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Õve got expansion vRAM
move.b #Sonora256K,SonoraVRAMSize(a3) ; otherwise, thereÕs only 256K out there
bra.s @EndSize
@512Ka add.l d0,d0 ; say thereÕ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Õ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Õ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Õve got expansion vRAM
move.b #Sonora512Kb,SonoraVRAMSize(a3) ; otherwise, thereÕ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Õs 1024K out there
@Set768Kb move.b #Sonora768Kb,SonoraVRAMSize(a3) ; say that thereÕ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:
;
; ¥ (R2) Panel ID Control ¥ (R3) Panel Setup
; ¥ (R4) Gray Scale ¥ (R5) Polynomial
; ¥ (R6) Panel Adjust ¥ (R7) ACDCLK
; ¥ (R8) Refresh Rate ¥ (R9) Blank Shade
; ¥ (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
;¥¥¥
;¥¥¥¥
;
; 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:
;
; ¥ a checksum
; ¥ an address test
; ¥ 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:
;
; ¥ (R6) Panel Type ¥ (R12) Display Format
; ¥ (R8) Panel Setup ¥ (R16) Refresh Rate
; ¥ (Ra) Output Format ¥ (R1c) Horz Skew Low
; ¥ (Rc) FRC Control ¥ (R28) LP Start
; ¥ (Re) M Adjust ¥ (R2a) LP Width
; ¥ (R10) N Adjust ¥ (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