supermario/base/SuperMarioProj.1994-02-09/OS/StartMgr/STCritTests.a
2019-06-29 23:17:50 +08:00

1226 lines
37 KiB
Plaintext

;
; File: STCritTests.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-1991 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <2> 9/18/91 JSM Add a header.
; <2.6> 7/17/89 GMR Added extra pass through memory if parity exists for Mod3Test
; and RevMod3Test.
; <2.5> 7/15/89 GMR Added Gary D's optimized Mod3Test and RevMod3Test.
; <2.4> 7/8/89 CCH Modified to work with Romulator.
; <2.3> 6/26/89 GMR Changed to use (sp) instead of sp when referencing memory chunk
; table, to work with new size memory output.
; <2.2> 6/20/89 rle create stub call to size memory--need to return pointer to table
; in d6 for board burn in
; <2.1> 6/11/89 GMR Changed ref's to BaseOfRom to be BigLEA's.
; <2.0> 5/26/89 rle cleaned up file to remove obsolete code; address line test now
; runs the same for all machines (depends upon memory size
; location table)
; <1.9> 5/16/89 rle modified mod3 and revmod3 tests to run an additional pass for
; parity ram testing when parity ram is installed; modified
; address line test to function correctly for bank a only/bank b
; only/bank a and bank b systems; added dynamic bus sizing test
; <1.8> 4/11/89 rle import BaseOfRom for stub file builds
; <1.7> 3/28/89 rle now uses equates from "STEqu.a"
; <1.6> 3/6/89 GGD Modified to use pc-relative BaseOfROM instead of hard coded
; ROMStart equate to make code less hardware dependent.
; <1.5> 2/21/89 rwh fixed AddrLineTest to not use MacII code for FourSquare.
; <1.4> 2/16/89 rwh added support for Fitch Memory Controller rev 1. When FMC2
; arrives, may need to change these for a contiguous physical
; memory model.
; <1.3> 2/10/89 RLE update equates to support minimal f-19 build
; <1.2> 2/6/89 RLE replaced NuMac conditionals with more generic identifiers
; <1.1> 2/2/89 RLE STCritTests.a is now an independent file, responsible for
; importting and exportting the procedures it needs and others
; need; fixed a lot of conditional statements to make them more
; generic and less CPU-specific; adjusted address line test to run
; on MDU-based machines; still need to make it run from bank B
; <1.0> 1/11/89 RLE derived from version 1.4 of StartTest.a modified version history
; markers for all old versions to start with "[" instead of
; "<"--this allows changes in STCritTeststo be tracked separately;
; the SizeMemory routines were removed from this section; they are
; now under OS group control; we just jump to SizeMemory to find
; out the top of logical/physical memory
;
PRINT OFF
LOAD 'StandardEqu.d'
INCLUDE 'HardwareEqu.a'
INCLUDE 'STEqu.a' ; <v1.7>
IF hasIopScc THEN ; <v1.1>
INCLUDE 'IOPequ.a'
ENDIF
PRINT ON
IF CPU = 20 THEN
MACHINE MC68020
ENDIF
IF CPU = 30 THEN
MACHINE MC68030
ENDIF
STRING ASIS
CritProc PROC ; <v1.1>
EXPORT SizeMem ; <v2.2>
EXPORT Mod3Test
EXPORT RevMod3Test
EXPORT ExtRAMTest
EXPORT AddrLineTest
EXPORT DataBusTest
EXPORT StartUpROMTest
EXPORT RomTest
EXPORT NoTest
IF CPU > 10 THEN ; <v1.9>
EXPORT dynamic_bussize_test ; <v1.9>
ENDIF ; <v1.9>
IMPORT BaseOfRom ; <v1.8>
IMPORT SizeMemory ; <v2.2>
IMPORT RomLoc ; <v2.4>
IF hasMac2Via2 THEN ; <v1.1>
IMPORT BankASize ; <v1.1>
ENDIF ; <v1.1>
;--------------------------------------------------------------------------- <v2.2>
; This routine calls the OS SizeMemory routine, and returns the pointer <v2.2>
; to the memory location table in register d6. This is required for use <v2.2>
; with the test manager serial interface for board burn in. <v2.2>
;--------------------------------------------------------------------------- <v2.2>
;
SizeMem ; <v2.2>
move.l a6,a4 ;save return address (a4 not destroyed) <v2.2>
bsr6 SizeMemory ;make OS call <v2.2>
move.l (sp),d6 ;return start of memory location table <v2.2><v2.3>
jmp (a4) ;go back home <v2.2>
;
;---------------------------------------------------------------------------
; 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
IF CPU = 00 THEN ; <v1.1>
move.l d6,d0 ;copy of longword bad bits
swap d0 ;bad bit mask to lower word
or.w d0,d6 ;
and.l #$0000FFFF,d6 ;only lower word [A322>
ENDIF
jmp (a6) ;return to caller, no errors
;
;---------------------------------------------------------------------------
; 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 #0,d0 ;clear checksum accumulator
moveq #0,d1 ;clear scratch
BigLea BaseOfROM,a0 ;point at ROM start, expected checksum <v1.6><2.1>
move.l (a0)+,d4 ;load up expected
move.l #myROMsize,d3 ;get appropriate size of ROM image less exp sum size
ROMLoop
move.w (a0)+,d0 ;fetch a ROM word
add.l d0,d1 ;add to checksum
subq.l #1,d3 ;count a loop
bne.s ROMLoop ;until done...
nop ;some nops for debug (leave these here for emulator use)
nop ;some nops for debug
eor.l d4,d1 ;result should be zero
CkSumBr beq.s @10
IF forRomulator THEN ; <2.4>
TestInRam A0 ; are we running in RAM? <2.4>
bne.s @10 ; if so, force chksum good <2.4>
ENDIF ; <2.4>
move.w #$FFFF,d6 ;set a failed code in result register [A310>
@10 jmp (a6) ;and exit
;---------------------------------------------------------------------------
;
; 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 ; <2.5>
@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
IF hasRBV THEN ; <v2.6>
cmp.w #ErrParRAM,d7 ;have we finished parity ram test? <v2.6>
beq @exit ;yep, we're outta here <v2.6>
ENDIF ; <v2.6>
; 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
IF CPU=00 THEN ; <1.1>
swap d0 ;bad bit mask to lower word
or.w d0,d6 ;
and.l #$0000FFFF,d6 ;only pass back lower word mask
ENDIF
IF hasRBV THEN ; <v2.6>
btst #parity,d7 ;determine need for parity ram test <v2.6>
beq.s @exit ;no parity ram, we're done <v2.6>
move.w #ErrParRAM,d7 ;set parity ram error code <v2.6>
movem.l Mod3Pat+4,@FillRegs ;load up 2 copies of the test patterns <v2.6>
bra @FillDone ;do one more pass if parity ram installed <v2.6>
ENDIF ; <v2.6>
@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
dc.l $B6DB6DB6
;---------------------------------------------------------------------------
;
; 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 ; <2.5>
@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
IF hasRBV THEN ; <v2.6>
cmp.w #ErrParRAM,d7 ;have we finished parity ram test? <v2.6>
beq @exit ;yep, we're outta here <v2.6>
ENDIF ; <v2.6>
; 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
IF CPU=00 THEN ; <1.1>
swap d0 ;bad bit mask to lower word
or.w d0,d6 ;
and.l #$0000FFFF,d6 ;only pass back lower word mask
ENDIF
IF hasRBV THEN ; <v2.6>
btst #parity,d7 ;determine need for parity ram test <v2.6>
beq.s @exit ;no parity ram, we're done <v2.6>
move.w #ErrParRAM,d7 ;set parity ram error code <v2.6>
movem.l RevMod3Pat+4,@FillRegs ;load up 2 copies of the test patterns <v2.6>
bra @FillDone ;do one more pass if parity ram installed <v2.6>
ENDIF ; <v2.6>
@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
dc.l $B6DB6DB6
;---------------------------------------------------------------------------
; 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, and d means ROM 0
;
; This test assumes interrupts are masked out with #$2500.
;
;---------------------------------------------------------------------------
;
RomTest
lea myROMSums,a1 ;point to end of first area
BigLea BaseOfROM,a0 ;point to start of ROM code <v1.6><2.1>
move.l (a0)+,d0 ;discard first long word of ROM
move.l a1,a2 ;keep a copy
clr.l d0 ;clear summing registers
clr.l d1
clr.l d2
clr.l d3
clr.l d4
clr.l d5
IF CPU = 00 THEN ; <v1.2>
@10 move.w (a0)+,d5 ;read out 2 bytes
move.b d5,d4 ;get byte 1
add.l d4,d1 ;byte 1 sum
lsr.l #8,d5 ;align next byte
move.b d5,d4 ;get byte 0
add.l d4,d0 ;byte 0 sum
ELSE ; <v1.2>
@10 move.l (a0)+,d5 ;read out 4 bytes
move.b d5,d4 ;get byte 3
add.l d4,d3 ;byte 3 sum
lsr.l #8,d5 ;align next byte
move.b d5,d4 ;get byte 2
add.l d4,d2 ;byte 2 sum
lsr.l #8,d5 ;align next byte
move.b d5,d4 ;get byte 1
add.l d4,d1 ;byte 1 sum
lsr.l #8,d5 ;align next byte
move.b d5,d4 ;get byte 0
add.l d4,d0 ;byte 0 sum
ENDIF
cmpa.l a0,a1 ;done yet?
bgt.s @10
; Now we jump past the 16 bytes of sums that live in low ROM space.
adda.l #16,a0 ;pointing at code again
lea myROMEnd,a1 ;and end of ROM image + 1
IF CPU = 00 THEN ; <v1.2>
@15 move.w (a0)+,d5 ;read out 2 bytes
move.b d5,d4 ;get byte 1
add.l d4,d1 ;byte 1 sum
lsr.l #8,d5 ;align next byte
move.b d5,d4 ;get byte 0
add.l d4,d0 ;byte 0 sum
ELSE ; <v1.2>
@15 move.l (a0)+,d5 ;read out 4 bytes
move.b d5,d4 ;get byte 3
add.l d4,d3 ;byte 3 sum
lsr.l #8,d5 ;align next byte
move.b d5,d4 ;get byte 2
add.l d4,d2 ;byte 2 sum
lsr.l #8,d5 ;align next byte
move.b d5,d4 ;get byte 1
add.l d4,d1 ;byte 1 sum
lsr.l #8,d5 ;align next byte
move.b d5,d4 ;get byte 0
add.l d4,d0 ;byte 0 sum
ENDIF
cmpa.l a0,a1 ;done yet?
bgt.s @15
; a2 still points to the table of expected checksums in low ROM...
; Check all 4 even though on Aladdin bytes 2,3 will be 0.
move.l (a2)+,d4 ;byte 0 expected checksum
eor.l d4,d0 ;any error?
beq.s @20 ;no
bset #0,d6 ;yes, flag byte 0 checksum error
@20 move.l (a2)+,d4 ;byte 1 expected checksum
eor.l d4,d1 ;any error?
beq.s @30 ;no
bset #1,d6 ;yes, flag byte 1 checksum error
@30 move.l (a2)+,d4 ;byte 2 expected checksum
eor.l d4,d2 ;any error?
beq.s @40 ;no
bset #2,d6 ;yes, flag byte 2 checksum error
@40 move.l (a2)+,d4 ;byte 3 expected checksum
eor.l d4,d3 ;any error?
beq.s @50 ;no
bset #3,d6 ;yes, flag byte 3 checksum error
@50 jmp (a6) ;exit test
;---------------------------------------------------------------------------
; 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
bne.s @1000 ;error
subq.l #1,d2 ;count it
bne.s @60 ;until done
jmp (a6) ;return no error
@1000 or.l (a2),d6 ;or in bad bits
IF CPU = 00 THEN ; <v1.1>
move.l d6,d0 ;copy 32 bit mask
swap d0 ;bad bit mask to lower word
or.w d0,d6 ;
and.l #$0000FFFF,d6 ;only pass back lower word mask
ENDIF
jmp (a6)
;---------------------------------------------------------------------------
; AddrLineTest
;
; This test writes a pattern in each memory address according to its address bit,
; then reads each back and verifies the pattern. This is then repeated in reverse.
;
; The addresses tested are $0,$4,$8,$10,$20,$40...$n00000.. to bank A bound if
; more than 1 bank exists, or to bank A bound div 2 if only one bank.
;
; On entry: d6 = 0
; a6 = return address
; (sp) = pointer to memory location table
;
; On exit: d6 = bit map of any bad address line, 0 if no errors
; a6 = return address
; (sp) = pointer to memory location table
;
;---------------------------------------------------------------------------
AddrLineTest
;;compute top of memory <v1.9>
move.l (sp),a1 ;move memory table pointer into a1 <v1.9><v2.3>
addq.l #8,a1 ;point to end of table for one bank systems <v1.9>
move.l #$01ffffff,d4 ;set up mask <v1.9>
@402 cmpi.l #-1,(a1) ;search for end of table <v1.9>
beq.s @404 ;found it! <v1.9>
move.l (sp),a1 ;move memory table pointer into a1 <v1.9><v2.3>
move.l (a1)+,a2 ;move beginning of bank A into a2 <v1.9>
add.l (a1)+,a2 ;compute top of bank A <v1.9>
addq.l #8,a1 ;point to next location field <v1.9>
bra.s @02 ;skip ahead <v1.9>
@404 subq.l #8,a1 ;go back to last location <v1.9>
move.l (a1)+,a0 ;move beginning memory location to a0 <v1.9>
add.l (a1)+,a0 ;add size to memory location to point to top <v1.9>
IF onMac | onMacPP | onHcMac THEN ;
move.l (sp),a1 ;move memory table pointer into a1 <v1.9><v2.3>
move.l (a1)+,a0 ;move beginning of bank A into a0 <v1.9>
add.l (a1)+,a0 ;compute top of bank A <v1.9>
move.l a0,d0 ;get top of memory
lea K512,a2 ;prep with top of 512K constant
cmp.l #Meg1,d0 ;see if RAM size > 1Meg
ble.s @000 ;yes it is
lea Meg2,a2 ;prep with top of 2Meg constant
@000
ELSE ; <v1.9>
move.l (sp),a1 ;move memory table pointer into a1 <v1.9><v2.3>
move.l (a1)+,a2 ;move beginning of bank A into a2 <v1.1>
add.l (a1)+,a2 ;compute top of bank A <v1.1>
ENDIF ; <v1.1>
; Now a2 has the top of bank A + 1, lets first see if thats the top of [contiguous] RAM
cmp.l a2,a0 ;a2 = top of Bank A, a0 = top of RAM
bgt.s @05 ;there is more than 1 bank
@02 move.l a2,d0 ;there is only 1 bank, so shift test address
lsr.l #1,d0
and.l d4,d0 ;mask out bank starting location <v1.9>
move.l d0,a2 ;and use it as the top address to test
@05
move.l (sp),a1 ;move memory table pointer into a1 <v1.9><v2.3>
move.l (a1),a1 ;load up beginning of bank A <v1.1>
clr.l (a1) ;clear first address in bank A <v1.1>
moveq #4,d5 ;first test data
@10 move.l d5,a3 ;generate test address
add.l a1,a3 ;add offset if necessary <v1.9>
move.l d5,(a3) ;write test data to test address
lsl.l #1,d5 ;calculate next test data *2
cmp.l a2,d5 ;see if done
ble.s @10
; Data has been written, read back in forward direction and verify
move.l (sp),a3 ;move memory table pointer into a1 <v1.9><v2.3>
move.l (a3),d0 ;should be 0
and.l d4,d0 ;mask out bank starting location <v1.9>
bne.s @1000 ;... else error
moveq #4,d5 ;first test data/address
@20 move.l d5,a3 ;generate test address
add.l a1,a3 ;add offset if necessary <v1.9>
move.l (a3),d0 ;read test data from test address
eor.l d5,d0 ;as expected?
bne.s @1000 ;no, error
lsl.l #1,d5 ;calculate next test data *2
cmp.l a2,d5 ;see if done
ble.s @20
; Now write data in backward direction, high to low addresses
move.l a2,d5 ;generate test data
lsl.l #1,d5 ;prime with 2*test data/address
@30 lsr.l #1,d5 ;calculate next test data div 2
cmp.l #4,d5 ;until data/address < 4
blt.s @35 ;until test data/address < 0
move.l d5,a3 ;generate test address
add.l a1,a3 ;add offset if necessary <v1.9>
move.l d5,(a3) ;write test data to test address
bra.s @30 ;again
; Data has been written, read back forward and verify
@35 sub.l a3,a3 ;start at RAM bottom again
add.l a1,a3 ;add offset if necessary <v1.9>
move.l (a3),d0 ;should be 0
and.l d4,d0 ;mask out bank starting location <v1.9>
bne.s @1000 ;... else error
moveq #4,d5 ;first test data/address
@40 move.l d5,a3 ;generate test address
add.l a1,a3 ;add offset if necessary <v1.9>
move.l (a3),d0 ;read test data from test address
eor.l d5,d0 ;as expected?
bne.s @1000 ;no, error
lsl.l #1,d5 ;calculate next test data *2
cmp.l a2,d5 ;see if done
ble.s @40
clr.l d0 ;done, clear error accumulator
@1000 move.l d0,d6 ;set any failed bits for caller
jmp (a6) ;return to caller
;
;---------------------------------------------------------------------------
; No Test implemented
;
;---------------------------------------------------------------------------
NoTest
moveq #0,d6
jmp (a6)
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
;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
jmp (a6) ;return to caller
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <v1.9>
END ; <v1.1>