sys7.1-doc-wip/OS/StartMgr/USTCritTests.a
2019-07-27 22:37:48 +08:00

1153 lines
38 KiB
Plaintext

;
; 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):
;
; <SM5> 01/07/93 HY In AddrLineTest save return address in A4 instead
; of A3 before calling SizeMemory.
; <SM4> 8/20/92 CCH Removed unneeded “forRisc” conditional.
; <SM3> 7/13/92 CCH Don't check checksum when running on Cub Card.
; <SM2> 5/2/92 kc Roll in Horror. Comments follow:
; <H2> 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.
; <T5> 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).
; <T4> 12/14/90 HJR Cleaned up the ROM checksum routines.
; <T3> 9/9/90 CCH Fixed StartupROMTest to deal with one-meg ROMs as well.
; <T2> 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><v1.6><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<T5>
bra.s @exit ; therefore, force a good checksum <2.4><T5>
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><SM5>
BSR6 SizeMemory ;Size all of memory <7>
movea.l a4,a6 ;Restore the return address <7><SM5>
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