mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 16:31:01 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
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
|
||
|
||
|