; ; 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): ; ; 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ ; machines. ; 11/8/93 JRH boxDBLite16 is now boxPowerBookDuo250. boxDBLite20 is now ; boxPenLite. ; 8/17/93 SAM Placed conditional forSmurf around the smurf stuff. ; 8/12/93 BG Removed reference to boxWLCDc1 as such a thing will never exist. ; Updated other boxflags to their "official" names. ; 8/11/93 KW just changed the name of boxRISCWombat to boxRiscCentris650 ; 8/4/93 JDR Removed redefinitions of private sound info, and now include ; SoundPrivate.a ; 01-11-93 jmp Updated various BoxFlag names. ; 12/23/92 RC Added Support for Smurf on Wombat ; 12/06/92 HY Added LC II support. ; 11/3/92 rab Add comments for Horror roll in . Comments follow: ; 10/6/92 NJV Added support in Sound Interrupt test for testing both channels ; on a Wombat. ; 10/5/92 NJV Fixed some bugs in the Sound Interrupt diagnostic tests that ; were causing interrupts to be lost. ; 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. ; 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. ; 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). ; 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. ; 8/2/92 AL Fixed TestVRAM for DBLite. ; 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. ; 7/15/92 AL Fixed TestASC to support DBLite. ; 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. ; 6/26/92 BG Added WLCD20, WLCD25, WLCDc1, Wombat20, and Wombat25 to the list ; of machines with optional FPUs. ; 6/17/92 AL Polished up the PG&E and GSC tests for DBLite. ; 6/7/92 AL Fixed a minor problem with a comment that wasn't separated ; from the code by a semicolon. Hardly worth mentioning. ; 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. ; 11/3/92 rab Roll in Horror changes. ; 10/25/92 HY Add support for boxMacLCII boxflag. ; 5/23/92 RB Making Cyclone changes... 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. ; 5/1/92 kc Roll in Horror. Comments Follow: ; 3/17/92 SWC Renamed boxDBLite->boxDBLite25 and boxDBLiteLC->boxDBLite33, and ; added boxDBLite16 and boxDBLite20 to the optional FPU list. ; 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. ; 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. ; 1/14/92 SWC Added DB-Lite LC to the list of boxes with optional FPU. Changed ; boxTIM to boxPowerBook170. ;
12/16/91 SWC Changed DB-Lite's VRAM size to 256K now that we have GSC. ;
11/25/91 CCH Use standard VIA equates. ;

10/28/91 SWC Added code to SizeVRAM to support DB-Lite. ;

9/10/91 CMP Added code to test for SWIM2 in TestSWIM ;

8/22/91 SWC Added DB-Lite to list of boxes with optional FPU. ; ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ ; Pre-HORROR ROM comments begin here. ; ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ ; 4/22/91 BG Rolled in Scott Smyers changes: Fixed the SCC internal loopback ; test for Spike at startup. ; 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. ; 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. ; 3/13/91 CCH Rolled in RBI changes from Scott Smyers. ; 2/18/91 djw Rolled in Scott Smyers' changes ; 1/14/91 CCH Rolled in Scott Smyers' changes. ; 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. ; 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. ; 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 ; EXPORT EgretTest ;<8> EXPORT TestSndInts ;<8> EXPORT TestCLUT ;<21> EXPORT TestVRAM ;<23> EXPORT TestC96 ; EXPORT TestGSCRegs EXPORT PGESelfTest EXPORT TestCSCRegs EXPORT SetSCCIOPBypass ; IMPORT QuasiPwrMgr IMPORT TM_SendByte ;<8> IMPORT TM_GetByte ;<8> IMPORT TM_Wait ;<8> IMPORT CudaReadByte ; rb IMPORT CudaWriteByte ; rb IMPORT RdXByte ; IMPORT WrXByte ; IMPORT ClkWpOff ; IMPORT IntLevel7 IMPORT SendEgretCmd ; IF hasPowerMgr THEN ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; #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 ; TestInRAM a2 ;are we running in RAM? beq.s @DoTest ;perform the test not moveq.l #-2,d6 ;else, report something unique RTS6 ;and return @DoTest ; ENDIF move.w sr,-(sp) ; ori.w #hiIntMask,sr ;turn ints off movec.l cacr,d3 ;get the cacr register value move.l d3,-(sp) ;save it bclr.l #CACR_IE_040,d3 ;disable the '040 instruction cache (no affect movec.l d3,cacr ;on '030s because this bit doesn't exist) 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 movec.l d3,cacr ;and restore it 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 ; TestInRAM a2 ;are we running in RAM? beq.s @DoTest ;perform the test not moveq.l #-2,d6 ;else, report something unique RTS6 ;and return @DoTest ; 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 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 @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, bset #ifIRQ,(sp) ; make sure the "any IRQ" bit is set, move.b d1,RvSEnb(a2) ; and disable them move.b RvIER(a2),-(sp) ;save other interrupt enables bset #ifIRQ,(sp) ; make sure the "any IRQ" bit is set, 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 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 movea.l DecoderInfo.VIA1Addr(a0),a2 ;point to VIA1 base <21><1.9> move.b d1,VIER(a2) ;turn off VIA1 interrupts 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 @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 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 ; TestInRAM a2 ;are we running in RAM? beq.s @DoTest ;perform the test not moveq.l #-2,d6 ;else, report something unique RTS6 ;and return @DoTest ; 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< 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< 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 cmp.b #batmanSound,d3 ;Is this a batman sound implementation? <18> bne.s @NotOrigBatman ;Branch if not "original" Batman 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) cmp.b #batmanSound,d3 ;Is this a batman sound implementation? bne.s @NotBatman ;Branch if not "original" Batman lea sndrnBatRatsSonora,a4 ;Get test register pointer for Sonora-style batman lea sndrdBatRatsSonora,a3 ;and get the test data bra.s @GoTest ;and go test that chip! @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 ; beq @exit ; skip this also move.b ascVersion(a1),d3 ; get the ASC version andi.b #$F0,d3 ; get the upper nibble cmp.b #batmanSound,d3 ; is this a batman? beq.w @exit ; exit now if it is 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> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Register table for Sonora-style Batman implementation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sndrnBatRatsSonora ; dc.w ascMode, 1, $01 ;mode register (always 1) dc.w ascVolControl, 8, $E0 ;volume register (bits 5-7) dc.w ascPlayRecA, 3, $01 ;sound in ctl reg dc.w $FFFF, $FFFF, $FFFF ; sndrdBatRatsSonora ; dc.b 1 ;mode register 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 dc.b 0,1,0 ;play/rec bit-leave in play ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <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 @checkSonora btst.l #SonoraExistsBit,d1 ; check for Sonora variant beq.s @3 ; continue if not lea rbvrdSonora,a3 ; else use the Sonora RBV register table 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 dc.b $0F,$00,$00 ; mask for bit patterns dc.b $78,$7F ; mask for set/clear patterns 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 ; out a floppy on a Swim2 machine 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: bsr Check4SWIM2 ; SWIM2 present? <3> ; beq.w SetupRegTest ; yes, skip pRAM tests <3> beq.w Swim2PramTest ; yes, test Swim2 pRAM <3> 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 ; 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 and.b (a3,d1),d3 ; mask it because of the funky way Swim2 PRAM works cmp.b d3,d0 ; and compare parameter RAM bytes 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 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 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 and.b (a3,d1.w),d0 ; mask the value for safety's sake move.b (a1,d2.w),d3 ; get the original data and.b (a3,d1.w),d3 ; mask it cmp.b d3,d0 ; see if they match 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 ;______________________________________________________________________________ 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 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) ; 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 ; move.b 0(a1,d1),d2 ; move.b d0,d6 ;load error value into d6 or.w #$0900,d6 ;set flag into d6 swap d6 ; or.w d2,d6 ;load expected value into d6 lea Swim2testdone,a5 ; jmp RestoreSwim2PRAM ; ;______________________________________________________________________________ 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 ; move.b d0,d6 ;load error value into d6 or.w #$0A00,d6 ;set flag swap d6 ; or.w d2,d6 ;load expected data into d6 lea Swim2testdone,a5 ; jmp RestoreSwim2PRAM ; ;______________________________________________________________________________ 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 ; MOVE (SP)+,SR ;Enable interrupts RTS6 ;return to caller ;______________________________________________________________________________ <3> ; Routine: Check4SWIM2 <3> ; Inputs: A0 -- IWM base <3> ; Outputs: Z-bit set if SWIM2, cleared otherwise <3> ; D0 is trashed. <3> ;______________________________________________________________________________ <3> Check4SWIM2 ; <3> ; if we get to here then we have either a SWIM or SWIM2, if we can get <3> ; back into IWM mode it is a SWIM, if not it is a SWIM2 <3> MOVE.B #$F8,wZeroes(A0) ;Switch back to IWM register set <3> MOVEQ #$F5-256,D0 ;If we can write to the phase register <3> MOVE.B D0,wPhase(A0) ;and read back the same value, this <3> CMP.B rPhase(A0),D0 ;must be an SWIM2 <3> BNE.S @1 ;-> mismatch: SWIM <3> MOVEQ #$F6-256,D0 ; <3> MOVE.B D0,wPhase(A0) ; <3> CMP.B rPhase(A0),D0 ; <3> BNE.S @1 ;-> mismatch: SWIM <3> MOVEQ #$F7-256,D0 ; <3> MOVE.B D0,wPhase(A0) ; <3> CMP.B rPhase(A0),D0 ; <3> RTS ; return with Z-bit set <3> @1 ; if we get here we must put the SWIM back into ISM mode <3> TST.B IntDrive(A0) ;Be sure the internal drive is selected <3> TST.B Q7L(A0) ;Select the mode register <3> TST.B MtrOff(A0) ; <3> TST.B Q6H(A0) ;get into status mode [Q7-Q6-Motor]=[010] <3> ; <3> MOVEQ #$40+iwminitmode,D0 ;set bit 6 to ISM mode and use the magic sequence <3> MOVE.B D0,Q7H(A0) ;Try to put the chip into ISM mode <3> MOVE.B #iwminitmode,Q7H(A0) ;The "magic sequence" is to set bit 6 <3> MOVE.B D0,Q7H(A0) ; to "1", "0", "1", "1" over four <3> MOVE.B D0,Q7H(A0) ; consecutive accesses <3> MOVEQ #1,D0 ; return with Z-bit cleared <3> RTS ; <3> ;______________________________________________________________________________ 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 ; Swim2Masks ; dc.b $00,$f0,$00,$f0 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; #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 ; ; ;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 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Floating point test equates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;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) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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 ; dc.b boxPowerBook170 ; dc.b boxPowerBookDuo210 ; dc.b boxPowerBookDuo230 ; dc.b boxPowerBookDuo250 ; dc.b boxDBLite20 ; dc.b boxLCIII ; dc.b boxVail16 ; dc.b boxCentris610 ; dc.b boxQuadra610 ; dc.b boxWombat20 ; dc.b boxCentris650 ; <26> IF forSmurf THEN ; dc.b boxRiscCentris650 ; ENDIF dc.b boxPrimus20 ; dc.b boxLC475 ; dc.b boxAladdin20 ; dc.b boxQuadra605 ; dc.b boxOptimus20 ; dc.b boxOptimus25 ; dc.b boxLC575 ; dc.b boxUnknown ; end of table ;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; 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 jmp (a6) ;return to caller 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 rb move.l ExtValid(a1),d0 ; rb andi.l #EgretFWMask,d0 ; mask all but Egret FW bits rb cmpi.l #Cuda,d0 ; chk for Cuda FW rb beq.w CudaTest ; If Cuda, go do it!!! rb ; else FW is Egret8 or Caboose, drop thru 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> 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 ; 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> 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 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 ; _______________________________________ ; rb, Cuda code ; ; _______________________________________ CudaTest ; ; Cuda Communications protocol is different from the Egret8 and Caboose, 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< gjs ;______________________________________________________ ; 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) ; 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 btst.l #VIA1Exists,d0 ;do we have a VIA1? beq.s @noVIA1 ;branch if not movea.l VIA1Addr(a0),a5 ;else, get the VIA1 address @noVIA1 ; ENDWITH ;<21> 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 ori.b #$80,(sp) ; make sure to set high bit for later move.b #$7f,(a3,d7.w) ; disable all via2 interrupts swap d7 ; d7 points to IFR move.b #$10,(a3,d7.w) ; clear pending via2 sound interrupts 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 beq.s @OriginalBatman ; we've got one, so work with both channels 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> 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 ; channel B and the record full/empty flag (Batman ; derivatives only, such as Sonora and djMEMC) bra.s @begin ; start the first test @OriginalBatman ; move.b d3,d6 ; put the sound type in the return status swap d6 ; move.w #$0F,d5 ; this is the FIFO interrupt mask for original Batman @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 cmp.b ascFIFOInt(a4),d5 ;are the FIFO(s) empty? 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 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 move.b #$10,(a3,d7.w) ;clear sound interrupt, if pending 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> @ChanB lea ascFifoRight(a4),a2 ;Point to channel B FIFO <17> @TestPlay move.b #$8,d6 ;initialize expected interrupt Chan B 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 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 move.b ascFifoInt(a4),d5 ;Get the FIFO status <18> 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 ; Batman sound implementation). For example, on Sonora, channel A is for record ; only, so we can't test play. We will jump down to the record tests if we're ; on a BatRat. D3 currently contains a masked sound version, so we need to ; get the "real" sound version and check it: move.b ascVersion(a4),d3 ; get the ASC version number cmp.b #batmanSound,d3 ; see if this is a "real" Batman ($B0) beq.s @realBatmanContinue ; continue if so cmp.b #wombatSound,d3 ; see if this is a Wombat batrat beq.b @WombatContinue ; go test channel B play for Wombat and.b #$f0,d3 ; mask it to see if it's a BatRat cmp.b #batmanSound,d3 ; and check beq.w @TestRecord ; branch down and test recording if so bra.s @realBatmanContinue ; default behavior from before @WombatContinue ; and.b #$f0,d3 ; mask it for BatRat move.l a2,d5 ; save for compare lea ascFifoLeft(a4),a2 ; get the address of channel A cmp.l a2,d5 ; see if we've already done this beq.w @TestRecord ; continue with the record test lea ascFifoLeft(a4),a2 ;Point to channel B FIFO bra.w @TestPlay ; @realBatmanContinue ; 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 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>(changed from beq.s to beq.w) 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>(changed from beq.s to beq.w) @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> swap d7 ; make d7 point to IER move.b #$10,(a3,d7.w) ; disable sound interrupts at via2 swap d7 ; make d7 point to IFR for Interrupt handler bset.b #7,ascFifoControl(a4) ; reset the FIFO ptr <17> bclr.b #7,ascFifoControl(a4) ; <17> move.b #$10,(a3,d7.w) ;Clear pending sound ints at via2 <18> bset.l #15,d6 ; and indicate record mode <17> 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 move.b #$90,(a3,d7.w) ; enable sound interrupts swap d7 ; d7 points to IFR for interrupt handler move.b #$3,ascPlayRecA(a4) ; set record mode, 22KHz Sample rate <17> move.w #$7fff,d5 ; initialise timeout counter <17> move.w #$2100,sr ; enable ints <17> @RecIntWt tst.b (a5) ; delay a bit <17> 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 @NoRecord clr.l d6 ; all is well @errexit ori.w #hiIntMask,sr ;turn ints off <17> swap d7 ; point d7 to the IER move.b #$10,(a3,d7.w) ; disable sound interrupts <17> swap d7 ;d7 points to IFR 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 move.b (sp)+,(a3,d7.w) ; restore enabled interrupts for via2 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> 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> 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> 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> 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> movea.l a0,a4 ;save this for later 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: 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 cmp.b #BoxMacLCII,d0 ; is this an LC II with V8? bne.s @checkSonora ; continue if not @itsLC lea V8DACwDataReg(a2),a3 ; a3 is the data register address lea V8DACwAddReg(a2),a0 ; a0 is the address register address bra.s @startClutTest ; branch down and start testing ; 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 to the one below WITH ProductInfo, DecoderInfo ; moveq.l #0,d4 ; clear my "started Omega" flag just in case 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 ; @genericVDAC ; lea vDACwDataReg(a2),a3 ;a3 is the data register address <28> lea vDACwAddReg(a2),a0 ;a0 is the address register address <28> @startClutTest ; 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 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 @skipSonoraRestore ; move.b (sp)+,vDACPixRdMask(a0) ;Restore the pixel mask movem.l (sp)+,a0/a2-a4/d1-d3 ;restore the registers <23><28> 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> cmp.b #BoxMacLC,d0 ;Is this an Elsie with V8? <28> beq.s @return ;no action necessary if not <28> cmp.b #BoxMacLCII,d0 ;is this an LC II with V8? beq.s @return ;no action necessary if not WITH ProductInfo ; move.l ExtValid(a1),d0 ; get the external valid flags btst.l #SonoraExistsBit,d0 ; check for Sonora (same VDAC on Vail as LC) bne.s @return ; no action necessary if so ENDWITH ; @clearRegs ; 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 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 Sonora256K Equ 0 ; Bank0=256K,Bank1=0 Sonora512Ka Equ 1 ; Bank0=256K,Bank1=256K Sonora512Kb Equ 4 ; Bank0=512K,Bank1=0 Sonora768Ka Equ 2 ; Bank0=256K,Bank1=512K Sonora768Kb Equ 5 ; Bank0=512K,Bank1=256K Sonora1024K Equ 6 ; Bank0=512K,Bank1=512K SonoraWrap Equ 512 ; EXPORT SizeVRAM SizeVRAM WITH ProductInfo, DecoderInfo, DecoderKinds MOVE.B DecoderKind(A1),D0 ; get the decoder type

CMPI.B #VISADecoder,D0 ; do we have a V8?

BNE.S @NotV8Video ; -> no

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 ;

RTS ;

@NotV8Video CMPI.B #JAWSDecoder,D0 ; do we have JAWS (Tim)?

BNE.S @NotJawsVideo ; -> no

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 ;

RTS ;

@NotJawsVideo ;

; From here to the below was added to support sizing Sonora VRAM: 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 above was added to support sizing Sonora VRAM. end CMPI.B #MSCDecoder,D0 ; do we have a MSC (DB-Lite)?

BNE.W @NotMSCVideo ; -> no

move.l #64*1024,D0 ; test this in 64k chunks to the next 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

addq.l #1,a4 ; bump the flag that tells us we've ; already done this once beq.s @FinishMSCVideo ; have we tested the first 64k? add.l d0,a0 ; no, so bump the addresses to the lea (a0,d0.l),a1 ; second 64k chunk @FinishMSCVideo MOVEQ #0,D6 ;

RTS ;

@NotMSCVideo ;

CMPI.B #OrwellDecoder,D0 ; do we have an Orwell (Spike,Eclipse)?

BNE @NotOrwellVideo ; -> no

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 ;

; 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 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 begin move.l a4,-(sp) ;preserve a4 across this test to the next ; 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 ; on a Sonora so that we can save and restore the VRAM sizing info: @notMSCDecoder ; cmpi.b #SonoraDecoder,ProductInfo.DecoderKind(a1) ;do we have Sonora (Vail)? bne.s @Begin ;no, so continue 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 move.b SonoraVRAMSize(a3),d0 ;and save the current VRAM size move.b d0,-(sp) ;for later restoration @Begin ; movem.l a0/a1,-(sp) ;save these bsr SizeVRAM ;go size VRAM movem.l (sp)+,a2/a3 ;restore them here (a0 & a1 now set for Mod3) cmp.l #-1,d6 ;does this apply? beq.l @noVRAM ;exit if not tst.l d0 ;else, do we have any VRAM anyway? beq.l @noVRAM ;exit if not cmpi.b #OrwellDecoder,DecoderKind(a3) ;is this a DAFB? ENDWITH ; end bne.s @normalTest ;continue if not movea.l a1,a2 ;save this for later movea.l a0,a1 ;set this up for starters moveq.l #0,d2 ;init the failed bit mask to zero @DAFBVRAMTestLoop movea.l a1,a0 ;the old end address is the new start address adda.l #DAFB_BankSize,a1 ;the new end address is the end of the next bank rol.w #4,d2 ;make room for this bank's error bits moveq.l #0,d6 ;zero out the results register movem.l d2/a2,-(sp) ;save some local registers BSR6 Mod3Test ;go test VRAM movem.l (sp)+,d2/a2 ;and restore our regs tst.l d6 ;how did this bank look? beq.s @StillOK ;continue if it was OK moveq.l #4-1,d3 ;otherwise, construct the failed byte lane mask @SetBits tst.b d6 ;was there a problem in this byte lane? beq.s @continue ;continue if not bset.l d3,d2 ;else, indicate the problem @continue ror.l #8,d6 ;go to the next byte lane failed bit mask dbra.w d3,@SetBits ;and keep going 'till done @StillOK cmpa.l a1,a2 ;are we done yet? bne.s @DAFBVRAMTestLoop ;keep going if not move.l d2,d6 ;put the failed mask into the result reg bra.s @EndTest ;then exit @normalTest ; movem.l a2/a3,-(sp) ;save the product & decoder info ptrs 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 ; 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 ; ; Restore the Sonora VRAM sizing info, if applicable: WITH DecoderKinds, DecoderInfo, ProductInfo ; cmpi.b #SonoraDecoder,DecoderKind(a1) ; do we have Sonora (Vail)? bne.s @Done ; -> 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 move.b (sp)+,d0 ; restore the original VRAM sizing info move.b d0,SonoraVRAMSize(a3) ; from what was saved prior to the test ENDWITH ; @Done ; move.l (sp)+,a4 ;restore a4 end rts ;and return <24> @noVRAM moveq.l #-1,d6 ;Indicate that test does not apply move.l (sp)+,a4 ;restore a4 rts ;and return to caller ;------------------------------------------------------------------------------- ; ; 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 ; ; 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 grayShade equ $0f ; tells the Blank Shade register to use this shade blankDisplay equ $00 ; tells the Gray Scale reg. to blank the screen resetVINT equ $80 ; tells the Gray Scale 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 ; v ; 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 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. move.b GSCBlankShade(a2),d2 ; get the Blank Shade register lsl.l #8,d2 ; free up the low byte for Panel Adjust reg. 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) ; or.b #grayShade,GSCBlankShade(a2) ; move.b #blankDisplay,GSCGrayScale(a2) ; ; 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 move.b (a3)+,d1 ; get the register to be tested bmi @GSCZero ; 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 @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 < below>>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 < above>>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) move.b (sp)+,(a2,d1.w) ; this register is done, so restore its original value bra.s @GSCZeroLoop ; all finished, and no error, so restore the ; 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 ; 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 @GSCDone ; restore the state of the machine and quit move.l (sp)+,d2 ; get the saved info move.b d2,GSCPanelAdj(a2) ; and restore it in the reverse order it was saved ror.l #8,d2 ; move.b d2,GSCBlankShade(a2) ror.l #8,d2 ; move.b #resetVINT,GSCGrayScale(a2) ; this is necessary because there may be a pending VINT ; interrupt that needs to be cleared or we'll hang the video 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 GSCRegMasks dc.b $07, $ff, $b8, $ff, $0f, $0f, $ff ; 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 - 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 ; ; 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 move.l a6,-(sp) ; save return address ori.w #hiIntMask,sr ; turn interrupts off moveq #0,d6 ; just in case move.w #$00EC,d3 ; command=$EC, length=0 to the one below BSR6 USTPMgrSendCommand ; send the command to the PMGR bne.s @Done ; -> error move.l #65,d5 ; loop this many times trying to get the response @retryLoop BSR5 USTPMgrRecvByte ; get the response byte in D3 dbeq d5,@retryLoop ; yes, we timed out so try again bne.s @Done ; we've allowed about 2 seconds, so bail ; 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 ; result of the self test in d6 swap d6 ; move the low byte into the high word @Done move.l (sp)+,a6 ; restore return address move.w (sp)+,sr ; restore interrupt level 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