mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-06 09:07:11 +00:00
6767 lines
256 KiB
Plaintext
6767 lines
256 KiB
Plaintext
;
|
||
; 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
|
||
|
||
|