; ; File: USTCritTests.a ; ; Contains: This file includes the critical test routines run at system start up. There are also ; some routines not run at startup but which are available to the Test Manager through ; the TJump Test Table. ; ; Copyright: © 1983-1993 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; 01/07/93 HY In AddrLineTest save return address in A4 instead ; of A3 before calling SizeMemory. ; 8/20/92 CCH Removed unneeded “forRisc” conditional. ; 7/13/92 CCH Don't check checksum when running on Cub Card. ; 5/2/92 kc Roll in Horror. Comments follow: ;

01/27/92 jmp (BG,Z6) Added padding in Mod3Test and RevMod3Test because of our ; STUPIP assembler optimizes things even when we dont want it to. ; Also, conditionalized the PROC parts of this file for use in ; lining up the UST part of HORROR with that of TERROR/Zydeco. ; 4/2/91 CCH Rolled in changes from Scott Smyers': Made the startupROM test ; always pass when built forRomulator but executed in ROM, not ; RAM. (it used to fail when run in ROM, but force a pass when run ; in RAM). ; 12/14/90 HJR Cleaned up the ROM checksum routines. ; 9/9/90 CCH Fixed StartupROMTest to deal with one-meg ROMs as well. ; 9/5/90 CCH Modifying ROM checksum test to deal with one-meg ROMs. ; <14> 1/23/92 RB Forced a good ROM checksum when compiled forRomulator. ; <13> 9/18/91 JSM Cleanup header. ; <12> 10/30/90 SS Tweeked fix <11> so that it uses the ROMHeader structure instead ; of equates in STEqu.a. ; <11> 10/22/90 SS Fixed the ROM checksum routines so that they do not rely on a ; build specific equate to get the ROM size. This is so that the ; same code will work when we go to a 1 Meg ROM without having to ; add another conditional flag to activate the 1 Meg ROM size ; equate. Also cleaned up the code a little in these routines. ; <10> 9/20/90 BG Removed <8>. 040s are now behaving more reliably. ; <9> 8/2/90 CCH Added NOPs between consecutive MOVEMs for flaky 040s. ; <8> 4/26/90 SS In AddrLineTest, return an error from SizeMemory if it fails. ; <7> 4/26/90 SS Rewrote the address line test to test all of memory, not just ; bank A. It will work even if banks are non-contiguous. I also ; added a call to SizeMemory to this test so that you don't have ; to run the SizeMem test immediately before running this one. ; <6> 4/24/90 SS In the byte lane ROM checksum test, I changed to use offsets for ; the address of the checksum in ROM and the end of ROM, instead ; of whole hardcoded addresses. ; <5> 4/20/90 SS Changed the way I increment a register in the extended RAM test ; to make it a little faster. ; <4> 3/30/90 SS Fixed a register usage problem which was destroying results in ; one of the RAM tests if an error was found on the last pattern ; test. Note that this test is only run in RBI and test manager - ; not on power up. ; <3> 2/16/90 SS Added flags to statements which were changed to support Ericson. ; <2> 2/12/90 MA Added moving inversions RAM test. It is not executed at ; startup, but is executed by the Test Manager the same as other ; mem. tests. ; <1.3> 8/22/89 GMR Included the rest of Fremonts critical tests in this file. ; <1.2> 7/25/89 CCH If forRomulator flag is set, checksum is forced good when ; running in RAM. ; <1.1> 7/15/89 GMR Fixed CPU=00 conditional for the RAM tests. ; <1.0> 6/13/89 GMR Added for first time to EASE. ; STRING ASIS CritProc PROC IMPORT BaseOfRom IMPORT SizeMemory ;<7> EXPORT Mod3Test EXPORT RevMod3Test EXPORT RomTest EXPORT StartUpROMTest EXPORT ExtRAMTest EXPORT AddrLineTest EXPORT DataBusTest EXPORT dynamic_bussize_test EXPORT MovInvTest ;<3> EXPORT NoTest ;--------------------------------------------------------------------------- ; ; Mod3Test is a fast test of the entire memory array. ; ; Inputs: a0 = bottom memory area to test ; a1 = top of memory area to test + 1 ; a6 = return to caller ; ; Outputs: d6.l is a failed bit mask ; a0,a1 still pointing to bottom and top of area to test ; ; Register usage: ; ; d0 = test data register ; d1 = test data register ; d2 = test data register ; d3 = test data register ; d4 = test data register ; d5 = test data register ; d6 = failed bit mask ; ; a0 = pointer to bottom test area ; a1 = pointer to top of test area ; a2 = copy of a0 ; a3 = unsued ; a4 = unused ; a5 = unused ; ; ; This test writes a modulo 3 pattern to all of memory, then shifts the ; pattern by writing the appropriate starting pattern, reading the next ; in memory, exclusive oring this with the previous location, then writing ; it back to the same location. Any errors while reading (or writing) are ; propagated to the end of memory. At the end of the test the last 3 long ; word entries must be as expected or an error has occurred. ; ; In order to properly determine the failing bank with this test, it is best ; to call the test with a0/a1 set to test one bank at a time. ; ; There are three cases that can occur at the end of memory, depending on ; what size memory is being tested. Observe the last three long words: ; ; Case 0: ; ; (LAST-12) $BD6BD6BD (LAST-8) $D6BD6BD6 (LAST-4) $6BD6BD6B ; ; Case 1: ; ; (LAST-12) $D6BD6BD6 (LAST-8) $6BD6BD6B (LAST-4) $BD6BD6BD ; ; Case 2: ; ; (LAST-12) $6BD6BD6B (LAST-8) $BD6BD6BD (LAST-4) $D6BD6BD6 ; ; The last three longs are compared against the appropriate table entries ; based on the case determined when memory is filled the first time. ; On exit, D6 reflects any bad bits found. ; ; This test should only be called with a0/a1 pointing at mod 4 bounds. The ; code assumes this and tests accordingly on 32 bit longword bounds, however ; calling this test with other bounds will result in a bus error since non- ; existent memory may be addressed. Also, upper - lower must be >= 24. ; ; This test assumes interrupts are masked out with #$2500. ;--------------------------------------------------------------------------- align 4 Mod3Test @FillRegs reg d0/d1/d2/d3/d4/d5 movem.l Mod3Pat,@FillRegs ;load up 2 copies of the test patterns movea.l a0,a2 ; starting address suba.w #120,a1 ; subtract slop from loop terminator bra.s @Fill120Start @Fill120Loop movem.l @FillRegs,(a2) movem.l @FillRegs,24(a2) movem.l @FillRegs,48(a2) movem.l @FillRegs,72(a2) movem.l @FillRegs,96(a2) adda.w #120,a2 ; point past block just written @Fill120Start cmpa.l a1,a2 ble.s @Fill120Loop ; fill until < 120 bytes remaining suba.w #12-120,a1 ; subtract slop from loop terminator moveq.l #12,d5 ; address increment value bra.s @Fill12Start @Fill12Loop movem.l d0-d2,(a2) adda.w d5,a2 ; point past bytes just written @Fill12Start cmpa.l a1,a2 ble.s @Fill12Loop ; fill until < 12 bytes remaining adda.w d5,a1 ; restore end address ; Now pick up the last maximum 8 bytes not written moveq #4,d4 ;case 0, offset = 4 cmpa.l a2,a1 ;maybe it came out even? beq.s @FillDone ;done filling memory move.l d0,(a2)+ ;write one more long moveq #8,d4 ;case 1, offset = 8 cmpa.l a2,a1 ;compare against real mem top beq.s @FillDone ;done filling memory move.l d1,(a2)+ ;write one more long moveq #0,d4 ;case 2, offset = 0 @FillDone movea.l a0,a2 ;copy starting address ; Memory is filled with the mod 3 pattern. The pattern is sequenced through ; three iterations for the test by exclusive oring in the following manner. move.l a1,d3 ;first get the top boundary sub.l a0,d3 ; = number of bytes to test subq.l #4,d3 ;less 4 bytes moveq.l #$3F,d2 ; mask for index into loop and.w d3,d2 ; compute the index neg.w d2 ; index backwards lsr.l #6,d3 ; 64 bytes per loop eor.l d1,(a2) ;write starting pattern addi.l #$FFFFFFFF,d5 ;help any floating bits float up jmp @61(d2.w) ; jump to the correct starting position @60 move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern move.l (a2)+,d2 ;read a pattern eor.l d2,(a2) ;generate next pattern @61 dbra d3,@60 ; until done subi.l #$00010000,d3 ; adjust outer loop count bpl.s @60 cmp.w #ErrParRAM,d7 ;have we finished parity ram test? beq @exit ;yep, we're outta here ; Now the final pass through the test area. cmp.l d0,d1 ; is this the second pass beq.s @62 ; if so, we're done move.l d0,d1 ; use pattern from D0 on final pass bra.s @FillDone ; make another pass @62 ; Now pick up the appropriate 3 longs nearest the end point. These should ; match patterns based on the case in d4, which was set up in the memory ; fill earlier. If any error occurred during eoring, it is propagated to the end. movem.l -12(a1),d0-d2 ;pickup last 12 bytes ; and remember d4 is still set up.. movem.l Mod3Pat(d4.w),d3-d5 ;get original test patterns eor.l d3,d0 eor.l d4,d1 eor.l d5,d2 or.l d2,d0 or.l d1,d0 ;compile final "bad bit" mask or.l d0,d6 ;record for caller btst #parity,d7 ;determine need for parity ram test beq.s @exit ;no parity ram, we're done move.w #ErrParRAM,d7 ;set parity ram error code movem.l Mod3Pat+4,@FillRegs ;load up 2 copies of the test patterns bra @FillDone ;do one more pass if parity ram installed @exit RTS6 ;and return ; Table of test and compare patterns Mod3Pat dc.l $6DB6DB6D ;case 2, offset = 0 dc.l $B6DB6DB6 ;case 0, offset = 4 dc.l $DB6DB6DB ;case 1, offset = 8 dc.l $6DB6DB6D dc.l $B6DB6DB6 dc.l $DB6DB6DB ;--------------------------------------------------------------------------- ; ; RevMod3Test is a fast test of the entire memory array, very similar to the ; Mod3Test above. It tests memory with the test addresses generated in the ; reverse direction. ; ; changed reg a3 to a2 in following code to make it like mod3test ; and to free-up a3 for other stuff ; ; Inputs: a0 = bottom memory area to test ; a1 = top of memory area to test + 1 ; a6 = return to caller ; ; Outputs: d6.l is a failed bit mask ; a0,a1 still pointing to bottom and top of area to test ; ; Register usage: ; ; d0 = test data register ; d1 = test data register ; d2 = test data register ; d3 = test data register ; d4 = test data register ; d5 = test data register ; d6 = failed bit mask ; ; a0 = pointer to bottom test area ; a1 = pointer to top of test area ; a2 = copy of a1 ; a3 = unused ; a4 = unused ; a5 = unused ; ; This test writes a modulo 3 pattern to all of memory, then shifts the ; pattern by writing the appropriate starting pattern, reading the next ; in memory, exclusive oring this with the previous location, then writing ; it back to the same location. Any errors while reading (or writing) are ; propagated to the beginning of memory. At the end of the test the first 3 ; long word entries must be as expected or an error has occurred. ; ; In order to properly determine the failing bank with this test, it is best ; to call the test with a0/a1 set to test one bank at a time. ; ; There are three cases that can occur at the end of memory, depending on ; what size memory is being tested. Observe the last three long words: ; ; Case 0: must write 3 more longs to fill memory, table offset = 8 for ; correct final compare patterns. ; ; (FIRST+0) $6BD6BD6B (FIRST+4) $BD6BD6BD (FIRST+8) $D6BD6BD6 ; ; Case 1: must write 1 more long to fill memory, table offset = 4 for ; correct final compare patterns. ; ; (FIRST+0) $D6BD6BD6 (FIRST+4) $6BD6BD6B (FIRST+8) $BD6BD6BD ; ; Case 2: must write 2 more longs to fill memory, table offset = 0 for ; correct final compare patterns. ; ; (FIRST+0) $BD6BD6BD (FIRST+4) $D6BD6BD6 (FIRST+8) $6BD6BD6B ; ; The first three longs are compared against the appropriate table entries ; based on the case determined when memory is filled the first time. ; On exit, D6 reflects any bad bits found. ; ; This test should only be called with a0/a1 pointing at mod 4 bounds. The ; code assumes this and tests accordingly on 32 bit longword bounds, however ; calling this test with other bounds will result in a bus error since non- ; existent memory may be addressed. Also, upper - lower must be >= 24. ; ; This test assumes interrupts are masked out with #$2500. ; ;--------------------------------------------------------------------------- align 4 RevMod3Test @FillRegs reg d0/d1/d2/d3/d4/d5 movem.l RevMod3Pat,@FillRegs ;load up 2 copies of the test patterns movea.l a1,a2 ; starting address adda.w #120,a0 ; add slop to loop terminator bra.s @Fill120Start @Fill120Loop movem.l @FillRegs,-(a2) movem.l @FillRegs,-(a2) movem.l @FillRegs,-(a2) movem.l @FillRegs,-(a2) movem.l @FillRegs,-(a2) @Fill120Start cmpa.l a2,a0 ble.s @Fill120Loop ; fill until < 120 bytes remaining adda.w #12-120,a0 ; add slop to loop terminator bra.s @Fill12Start @Fill12Loop movem.l d0-d2,-(a2) @Fill12Start cmpa.l a2,a0 ble.s @Fill12Loop ; fill until < 12 bytes remaining suba.w #12,a0 ; restore bottom address ; Now pick up the last maximum 8 bytes not written moveq #8,d4 ;case 0, offset = 8 cmpa.l a2,a0 ;compare against real mem bottom beq.s @FillDone ;done filling memory move.l d2,-(a2) ;write one more long moveq #4,d4 ;case 1, offset = 4 cmpa.l a2,a0 ;compare against real mem bottom beq.s @FillDone ;done filling memory move.l d1,-(a2) ;write one more long moveq #0,d4 ;case 2, offset = 0 @FillDone movea.l a1,a2 ;copy ending address subq.l #4,a2 ;adjust to last longint ; Memory is filled with the mod 3 pattern. The pattern is sequenced through ; three iterations for the test by exclusive oring in the following manner. move.l a2,d3 ;first get the top boundary sub.l a0,d3 ; = number of bytes to test moveq.l #$3F,d0 ; mask for index into loop and.w d3,d0 ; compute the index neg.w d0 ; index backwards lsr.l #6,d3 ; 64 bytes per loop eor.l d1,(a2) ;write starting pattern addi.l #$FFFFFFFF,d5 ;help any floating bits float up jmp @61(d0.w) ; jump to the correct starting position @60 move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern move.l (a2),d0 ;read a pattern eor.l d0,-(a2) ;generate next pattern @61 dbra d3,@60 ; until done subi.l #$00010000,d3 ; adjust outer loop count bpl.s @60 cmp.w #ErrParRAM,d7 ;have we finished parity ram test? beq @exit ;yep, we're outta here ; Now the final pass through the test area. cmp.l d2,d1 ; is this the second pass beq.s @62 ; if so, we're done move.l d2,d1 ; use pattern from D2 on final pass bra.s @FillDone ; make another pass @62 ; Now pick up the appropriate 3 longs nearest the end point. These should ; match patterns based on the case in d4. If any error occurred during ; eoring, it is propagated through to the end. movem.l (a0),d0-d2 ;pickup first 12 bytes movem.l RevMod3Pat(d4.w),d3-d5 ;get original test patterns eor.l d3,d0 eor.l d4,d1 eor.l d5,d2 or.l d2,d0 or.l d1,d0 ;compile final "bad bit" mask or.l d0,d6 ;record for caller btst #parity,d7 ;determine need for parity ram test beq.s @exit ;no parity ram, we're done move.w #ErrParRAM,d7 ;set parity ram error code movem.l RevMod3Pat+4,@FillRegs ;load up 2 copies of the test patterns bra @FillDone ;do one more pass if parity ram installed @exit RTS6 ;and return RevMod3Pat dc.l $6DB6DB6D ;case 2, offset = 0 dc.l $B6DB6DB6 ;case 0, offset = 4 dc.l $DB6DB6DB ;case 1, offset = 8 dc.l $6DB6DB6D dc.l $B6DB6DB6 dc.l $DB6DB6DB ;--------------------------------------------------------------------------- ; RomTest does a ROM checksum on the individual ROMs and returns an error ; code in d6 indicating any failed ROMs. The checksums are located in the ; ROMs at dedicated addresses, forever defined to be as follows: ; ; ROM 0 at ROMStart + $0030 - $0033 ; ROM 1 at ROMStart + $0034 - $0037 ; ROM 2 at ROMStart + $0038 - $003B ; ROM 3 at ROMStart + $003C - $003F ; ; On entry: d6 = 0 ; On exit: d6 = $0000000X, where X = abcd, and ; a means ROM 3, ; b means ROM 2, ; c means ROM 1, ; d means ROM 0 ; ; This test assumes interrupts are masked out with #$2500. ; ;--------------------------------------------------------------------------- RomTest WITH ROMHeader ; <12> BigLea BaseOfROM,a0 ;point to start of ROM code <11> lea CheckSum0(a0),a1 ;point to end of first area <12><11> move.l ROMSize(a0),d0 ;and size of ROM <12><11> lea.l (a0,d0.l),a2 ;calculate the end of ROM <11> ENDWITH clr.l d0 ;clear summing registers clr.l d1 clr.l d2 clr.l d3 clr.l d4 ;holds a byte from ROM to sum addq.l #4,a0 ;skip past first long word <11> @loop move.b (a0)+,d4 ; <11> add.l d4,d0 ;sum the HHSB <11> move.b (a0)+,d4 ; <11> add.l d4,d1 ;sum the MHSB <11> move.b (a0)+,d4 ; <11> add.l d4,d2 ;sum the MLSB <11> move.b (a0)+,d4 ; <11> add.l d4,d3 ;sum the LLSB <11> cmpa.l a0,a1 ;at checksum area yet? bne.s @checkTop ;no, see if at top adda.l #16,a0 ;yes, skip over checksums bra.s @loop ;and continue summing @checkTop cmpa.l a0,a2 ;end of ROM yet? bgt.s @loop ;no, keep summing @compare IF forRomulator THEN ; <1.2> TestInRam A0 ; are we running in RAM? <1.2> bne.s @exit ; if so, force chksum good <1.2> ENDIF ; <1.2> @byte1 cmp.l (a1)+,d0 ;byte 0 expected checksum beq.s @byte2 bset #0,d6 ;error, flag byte 0 checksum error @byte2 cmp.l (a1)+,d1 ;byte 1 expected checksum beq.s @byte3 bset #1,d6 ;error, flag byte 1 checksum error @byte3 cmp.l (a1)+,d2 ;byte 2 expected checksum beq.s @byte4 bset #2,d6 ;error, flag byte 2 checksum error @byte4 cmp.l (a1)+,d3 ;byte 3 expected checksum beq.s @exit bset #3,d6 ;error, flag byte 3 checksum error @exit RTS6 ;exit test ;--------------------------------------------------------------------------- ; StartUpROMTest is run normally only at system startup. It uses the longword ; checksum residing in location 0. The Test Manager also supports a checksum test ; that uses the 2 or 4 sums residing in locations ROMStart+$0030 through $003F ; as separate sums for each ROM chip. ; ;--------------------------------------------------------------------------- StartUpROMTest moveq.l #0,d0 ;clear checksum accumulator <11> moveq.l #0,d1 ;clear scratch <11> WITH ROMHeader ; <12> BigLea BaseOfROM,a0 ;point at ROM start, expected checksum <11><2.1> move.l ROMSize(a0),d3 ;get the size of the ROM (in bytes) <12><11> subq.l #4,d3 ;subtract size of checksum <11> move.l (a0)+,d4 ;load up expected checksum <11> ENDWITH @ROMLoop ; <11> move.w (a0)+,d0 ;fetch a ROM word <11> add.l d0,d1 ;add to checksum <11> subq.l #2,d3 ;decrement by 2 bytes <11> bne.s @ROMLoop ;continue until done <11> nop ;some nops for debug (leave these here for emulator use) nop ;some nops for debug eor.l d4,d1 ;result should be zero beq.s @exit ; <11> IF forRomulator THEN ;if we're built for the romulator, we'd never pass bra.s @exit ; therefore, force a good checksum <2.4> ENDIF ; <2.4> move.w #$FFFF,d6 ;set a failed code in result register [A310> @exit RTS6 ;and exit ;--------------------------------------------------------------------------- ; ExtRAMTest is a March pattern for testing RAM. The algorithm is: ; ; a) write zeros to all RAM incrementing addresses ; b) read/verify/invert incrementing ; c) read/verify/invert decrementing ; d) read/verify/invert incrementing ; e) read/verify decrementing ; ; On entry: ; ; a0 = points to start of test area ; a1 = points to end of test area ; ; Register usage: ; ; a0 = points to start of test area ; a1 = points to end of test area ; a2 = working address pointer ; ; d0 = data pattern ; d1 = inverted data pattern ; d2 = loop counter ; d3 = saved loop counter ; ; This test assumes interrupts are masked out, except for power off in NuMac. ; ;--------------------------------------------------------------------------- ExtRAMTest moveq #0,d0 ;starting data = 0 moveq #-1,d1 ;inverted data = $FFFFFFFF move.l a0,a2 ;copy start area move.l a1,d2 ;first get the top boundary sub.l a0,d2 ; = number of bytes to test lsr.l #2,d2 ;divide by 4 move.l d2,d3 ;and keep a copy @10 move.l d0,(a2)+ ;write a pattern subq.l #1,d2 ;count it bne.s @10 ;until done ; RAM is at all 0's now ; Now read/verify/invert incrementing move.l d3,d2 ;get count move.l a0,a2 ;and pointer @20 tst.l (a2) ;read/verify bne.s @1000 ;error eor.l d1,(a2)+ ;read/invert to 1's subq.l #1,d2 ;count it bne.s @20 ;until done ; RAM is at all 1's now ; Read/verify/invert decrementing, a2 points to 1 long past the top area move.l d3,d2 ;get count @30 eor.l d1,-(a2) ;read/invert to 0's bne.s @1000 ;error subq.l #1,d2 ;count it bne.s @30 ;until done ; RAM is at all 0's now ; Read/verify/invert incrementing, a2 points to start of test area move.l d3,d2 ;get count @40 tst.l (a2) ;read/verify bne.s @1000 ;error eor.l d1,(a2)+ ;read/invert to 1's subq.l #1,d2 ;count it bne.s @40 ;until done ; RAM is at all 1's now ; Read/verify/invert decrementing, a2 points to 1 long past the top area move.l d3,d2 ;get count @50 eor.l d1,-(a2) ;read/invert to 0's bne.s @1000 ;error subq.l #1,d2 ;count it bne.s @50 ;until done ; RAM is at all 0's now ; Read/verify incrementing, a2 points to start of test area move.l d3,d2 ;get count [C354> @60 tst.l (a2) ;read/verify <4> bne.s @1000 ;Error if ≠ 0 <4> addq.l #4,a2 ;Else, Increment a2 to point to next location <5><4> subq.l #1,d2 ;count it bne.s @60 ;until done RTS6 ;return no error @1000 or.l (a2),d6 ;or in bad bits RTS6 ;--------------------------------------------------------------------------- ; AddrLineTest ; ; This test writes a pattern in each memory address according to its address bit, ; then reads each back and verifies the pattern in reverse. ; ; On entry: a6 = return address ; ; On exit: d6 = failed bits of an address location, or error result from SizeMem <8> ; d7.b = if ≠ 0: bank number which failed (1 = bank A) <8> ; if = 0: Size memory failed; d6 contains the error from size mem <8> ; a6 = return address ; (sp) = pointer to memory location table ; ; Destroys a0-a3, d0, d5 ; ;--------------------------------------------------------------------------- AddrLineTest move.b #0,d7 ;Initialize the bank counter <8> movea.l a6,a4 ;Save Return address <7> BSR6 SizeMemory ;Size all of memory <7> movea.l a4,a6 ;Restore the return address <7> bne.s @VerError ;If size mem failed, error out <8> move.l (sp),a0 ;move memory table pointer into a0 <7> @NextBankFill add.b #1,d7 ;Increment the bank counter <7> move.l (a0)+,a1 ;Get the start addr of this bank <7> cmpa.l #-1,a1 ;is this all the banks? <7> beq.s @MemFilled ;go to check if so <7> movea.l (a0)+,a2 ;Get length of bank <7> move.l a1,(a1) ;Initialize the first location of the bank <7> moveq.l #4,d5 ;Start storing from offset 4 <7> @Fill move.l d5,a3 ;Get the starting offset <7> adda.l a1,a3 ;Add the base addr of this bank <7> move.l a3,(a3) ;write test data to test address <7> lsl.l #1,d5 ;calculate next test data <7> cmp.l a2,d5 ;see if done <7> blt.s @Fill ;Continue if not <7> bra.s @NextBankFill ;Else go to next bank <7> ; All banks now have the fill pattern. Verify this in the reverse direction <7> @MemFilled lea -4(a0),a0 ;point a0 to the 'end of chunk table' mark <7> @NextBankCheck sub.b #1,d7 ;Decrement the bank counter <7> movea.l -(a0),a2 ;Get the bank size from the chunk table <7> movea.l -(a0),a1 ;and the start address of this bank <7> moveq.l #4,d5 ;Initialize the starting offset <7> @adjust lsl.l #1,d5 ;Shift the test offset <7> cmp.l a2,d5 ;Is it greater than the bank size? <7> blt.s @adjust ;continue shifting if not <7> @check lsr.l #1,d5 ;Adjust the offset <7> move.l d5,d0 ;Calculate the test address <7> add.l a1,d0 ; <7> movea.l d0,a3 ; <7> move.l (a3),d6 ;Get the test data <7> eor.l d0,d6 ;Verify it <7> bne.s @VerError ;Error out if not zero <7> cmp.l #4,d5 ;was that the last location? <7> bgt.s @check ;Continue checking if not <7> tst.l d5 ;Have we tried an offset of zero yet? <7> beq.s @CheckCont ;Continue if so <7> moveq.l #0,d5 ;Else, let's try an offset of zero <7> bra.s @check ; <7> @CheckCont cmpa.l (sp),a0 ;Are we done yet? <7> bgt.s @NextBankCheck ;go on to next bank if not <7> move.b #0,d7 ;Success! Zero out the bank counter <7> @VerError ; <7> RTS6 ;Return <7> ;--------------------------------------------------------------------------- ; Data bus test walks 0 and 1 bits across the data buss to verify that ; memory can be accessed. ; ; On entry, a6 = return to caller. ; a0 = test address ; ; On exit, d6 = failed bit mask. ; ; Register usage: ; ; d0 = data bit register ; d1 = data bit register ; d2 = loop counter ; ; a0 = address pointer ; ; This test assumes interrupts are masked out with #$2500. ;--------------------------------------------------------------------------- ; DataBusTest moveq #1,d0 ;first data pattern is 1 in 0's moveq #-2,d1 ;next data pattern, $FFFFFFFE, 0 in 1's [C660>/[C798> move.w #$00FF,d2 ;loop counter = 256 @10 movem.l d0-d1,(a0) ;write test patterns eor.l d0,(a0) ;read and write low test location or.l (a0),d6 ;if any bad bits, or to fail reg eor.l d1,4(a0) ;read and write high test loc or.l 4(a0),d6 ;if any bad bits, or to fail reg rol.l #1,d0 ;rotate the bit rol.l #1,d1 ;rotate the bit dbra d2,@10 ;continue until bit shifted to carry RTS6 ;return to caller, no errors ;--------------------------------------------------------------------------- ;--------------------------------------------------------------------------- ;--------------------------------------------------------------------------- ;--------------------------------------------------------------------------- ;dynamic bus sizing tests ;table for dynamic bus-sizing test must be kept in this order dbs_table dc.l $00112233 ;pattern for 1st two lw's lw bound dc.l $88888888 dc.l $88001122 ;lw+1(offset) dc.l $33888888 dc.l $88880011 ;lw+2(offset) dc.l $22338888 dc.l $88888800 ;lw+3(offset) dc.l $11223388 dc.l $88888888 ;lw+4(offset) dc.l $00112233 ;expected patterns for word accesses dc.l $00118888 ;w+0(offset) dc.l $88888888 dc.l $88001188 ;w+1(offset) dc.l $88888888 dc.l $88880011 ;w+2(offset) dc.l $88888888 dc.l $88888800 ;w+3(offset) dc.l $11888888 dc.l $88888888 ;w+4(offset) dc.l $00118888 ;expected patterns for byte accesses dc.l $00888888 ;b+0(offset) dc.l $88888888 dc.l $88008888 ;b+1(offset) dc.l $88888888 dc.l $88880088 ;b+2(offset) dc.l $88888888 dc.l $88888800 ;b+3(offset) dc.l $88888888 dc.l $88888888 ;b+4(offset) dc.l $00888888 ;======================================================= ; ; dynamic_bussize_test: this test will verify that the dynamic bus sizing of the ; 68020/68030 and dram memory subsystem are working properly. ; this is accomplished by writing longword, word, and byte data ; to locations + offset within a constant field of two longwords ; and then verifying that the correct bytes were written that ; constant field of two longwords ; ; ; entry: a0.l = ptr to valid ram on longword boundary ; a6.l = return address for bsr6 ; ; exit: if pass ; d6.l = 0 ; ; else ; d6.l = bitmask of failures in the following format ; ; bit 0 set means lw + 0 (offset) test failed ; bit 1 set means lw + 1 (offset) test failed ; . ; . ; . ; bit 14 set means byte + 4 (offset) test failed ; ; see dbs_table for expected patterns ; ; ; altered: d0.l - d6.l, a1.l - a2.l ; ;======================================================= ;do longwords 1st dynamic_bussize_test move.l #%0111111111111111,d6 ;init failure mask lea.l dbs_table,a1 ;ptr to table of expected results lea.l dbs_table+4,a2 ;ptr to background pattern move.l #$00112233,d0 ;initialize write pattern clr.l d1 ;init bit position holder and offset values dbs_lwb1 move.l (a2),(a0) ;write background pattern 2 longwords move.l (a2),4(a0) move.l d0,(a0,d1.w) ;write pattern to ram lw + offset movem.l (a0),d2-d3 ;read back lw's on lw bounds movem.l (a1)+,d4-d5 ;get expected pattern from table cmp.l d4,d2 ;does 1st lw match expected bne.s dbs_lwb2 ;no, skip mask update cmp.l d5,d3 ;how about 2nd lw bne.s dbs_lwb2 ;no, skip mask update swap d1 ;get bit position info to update fail bitmask bclr.l d1,d6 ;clear appropriate bit to indicate pass this test swap d1 ;restore offset to lower word dbs_lwb2 addq.l #1,d1 ;bump address offset swap d1 ;get bit position info to update fail bitmask addq.w #1,d1 ;bump bit position to for next offset test swap d1 ;restore offset to lower word cmpi.b #4,d1 ;all offsets tried bls.s dbs_lwb1 ;no, do another ;;;;;;;;;;;;;; ;now do words dbs_word move.w #$0011,d0 ;initialize write pattern clr.w d1 ;init bit position holder and offset values @dbs_lwb1 move.l (a2),(a0) ;write background pattern 2 longwords move.l (a2),4(a0) move.w d0,(a0,d1.w) ;write pattern to ram lw + offset movem.l (a0),d2-d3 ;read back lw's on lw bounds movem.l (a1)+,d4-d5 ;get expected pattern from table cmp.l d4,d2 ;does 1st lw match expected bne.s @dbs_lwb2 ;no, skip mask update cmp.l d5,d3 ;how about 2nd lw bne.s @dbs_lwb2 ;no, skip mask update swap d1 ;get bit position info to update fail bitmask bclr.l d1,d6 ;clear appropriate bit to indicate pass this test swap d1 ;restore offset to lower word @dbs_lwb2 addq.l #1,d1 ;bump address offset swap d1 ;get bit position info to update fail bitmask addq.w #1,d1 ;bump bit position to for next offset test swap d1 ;restore offset to lower word cmpi.b #4,d1 ;all offsets tried bls.s @dbs_lwb1 ;no, do another ;;;;;;;;;;;;;;;;;;;;;;;; ;and finally bytes dbs_byte clr.l d0 ;initialize write pattern clr.w d1 ;init bit position holder and offset values @dbs_lwb1 move.l (a2),(a0) ;write background pattern 2 longwords move.l (a2),4(a0) move.b d0,(a0,d1.w) ;write pattern to ram lw + offset movem.l (a0),d2-d3 ;read back lw's on lw bounds movem.l (a1)+,d4-d5 ;get expected pattern from table cmp.l d4,d2 ;does 1st lw match expected bne.s @dbs_lwb2 ;no, skip mask update cmp.l d5,d3 ;how about 2nd lw bne.s @dbs_lwb2 ;no, skip mask update swap d1 ;get bit position info to update fail bitmask bclr.l d1,d6 ;clear appropriate bit to indicate pass this test swap d1 ;restore offset to lower word @dbs_lwb2 addq.l #1,d1 ;bump address offset swap d1 ;get bit position info to update fail bitmask addq.w #1,d1 ;bump bit position to for next offset test swap d1 ;restore offset to lower word cmpi.b #4,d1 ;all offsets tried bls.s @dbs_lwb1 ;no, do another RTS6 ;return to caller ; From here to next <3> flag below was added for Ericson ;--------------------------------- ; Moving Inversions Test (BIT). ;--------------------------------- ; ; ; Inputs: a0 = bottom memory area to test ; a1 = top of memory area to test + 1 ; a6 = return to caller ; ; Output: d6 is the error accumulator. ; MovInvTest move.l a0,a5 ; save starting address move.l a1,d3 sub.l a0,d3 ; size of block to test @1 clr.l (a0)+ ;set the memory to zero. sub.l #4,d3 bne @1 ; ; TOP OF FORWARD LOOP clr.l d1 move.w #4,d1 ;Address increment, start at 4 @2 move.l #0,a2 ;Address offset value ; ; TOP OF ADDRESS INCREMENT LOOP @3 move.l a5,a0 ;Starting address adda.l a2,a0 ;...plus offset ; ; TOP OF BIT SET LOOP clr.l d2 ;Bit to set clr.l d4 ;Expect pattern @4 move.l a0,a3 ;Working start address ; ; TOP OF WORKING ADDRESS LOOP @5 move.l (a3),d3 ;Read cmp.l d3,d4 ;...same as expected? bne @100 ;...no, flag as error bset d2,d3 ;Set the test bit move.l d3,(a3) ;...write, with test bit set move.l (a3),d5 ;...read again cmp.l d5,d3 ;...same as written? bne @101 ;...no, flag as error adda.l d1,a3 cmp.l a1,a3 ;At end of memory? bmi @5 ; BOTTOM OF WORKING ADDRESS LOOP ; move.l d5,d4 ;New expect data add.w #1,d2 ;Next bit cmp.w #32,d2 ;...at end? bne @4 ; BOTTOM OF BIT SET LOOP ; ; ; TOP OF BIT CLR LOOP clr.l d2 ;Bit to clear move.l #$FFFFFFFF,d4 ;Expect pattern @6 move.l a0,a3 ;Working start address ; ; TOP OF WORKING ADDRESS LOOP @7 move.l (a3),d3 ;Read cmp.l d3,d4 ;...same as expected? bne @100 ;...no, flag as error bclr d2,d3 ;Set the test bit move.l d3,(a3) ;...write, with test bit set move.l (a3),d5 ;...read again cmp.l d5,d3 ;...same as written? bne @101 ;...no, flag as error adda.l d1,a3 cmp.l a1,a3 ;At end of memory? bmi @7 ; BOTTOM OF WORKING ADDRESS LOOP ; move.l d5,d4 ;New expect add.w #1,d2 ;Next bit cmp.w #32,d2 ;...at end? bne @6 ; BOTTOM OF BIT CLR LOOP ; adda.l #4,a2 ;Next address base offset cmp.l d1,a2 ;...done all offsets? bne @3 ;...no, continue ; BOTTOM OF ADDRESS INCREMENT LOOP ; ; asl.l #1,d1 ;New Address increment value cmp.l #$80000,d1 ;...at end? bne @2 ;...no, continue ; BOTTOM OF FORWARD LOOP @99 move.l a5,a0 ; restore starting address rts6 ; @100 eor.l d3,d4 ;...same as expected move.l d4,d6 bra @99 ; @101 eor.l d5,d3 move.l d3,d6 bra @99 ; From here to next <3> flag above was added for Ericson ;--------------------------------------------------------------------------- ; No Test implemented ; ;--------------------------------------------------------------------------- NoTest moveq #0,d6 RTS6 ENDPROC